Note that for basic usage of push notifications in your app, the Free plan should be enough. If you have any specific requirements such as DPA and more sophisticated analytics data you might want to choose one of their paid plans.
3 – Activate your email
You will then receive a confirmation link in your email, make sure to check it and start the activation process.
4 – Answer questions
After clicking the activation email OneSignal will require you to answer a few quick questions:
5 – Create your first app
You will now be required to create your first OneSignal app, by choosing a name. Make sure to use the same name that you will use for your mobile app, this will avoid a lot of confusion.
6 – Skip the quick start guide
This is not a required step, as our team will configure everything for you. Make sure to skip this step:
That’s it! You now have your OneSignal account, make sure to check our guide on how to invite users to your account:
Google’s Firebase is an app development platform that gives you control over several parts of your app, with it you will be able to track analytics data, crashes, user behavior, ads, and much more.
Create your Firebase account
Just like other Google services, in order to have a Firebase account, you will need to sign in with your own Google Account login details here: https://firebase.google.com/
To publish your app on the App Store for iOS devices, you must have an Apple Developer Account. Below are the steps required to register for your own Apple Developer Account.
Requirements
Before enrolling, ensure you have the following:
1. Apple Account
If you use an iOS device, you likely already have an Apple Account. If not, you can create one quickly here: Create an Apple Account
2. Enable Two-Factor Authentication
Apple requires two-factor authentication (2FA) to be enabled on your Apple Account for security purposes. You can find instructions on enabling 2FA here.
3. DUNS Number (For Organizations)
If you are enrolling as a company, Apple requires a DUNS number. You can check if you have one or request a free DUNS number here: DUNS Number Lookup
Why Should I Enroll as a Company?
You must enroll as an organization if your company is a registered business entity such as:
Corporation (Corp., Inc.)
Limited Liability Company (LLC, LC, Ltd. Co.)
Legal entity (GmbH, AG, KG, oHg, etc.)
If you are a sole proprietor, you must register as an individual. Apple does not accept DBAs, fictitious businesses, trade names, or branches for company enrollment.
Benefits of an Organization Account:
Invite developers to collaborate on your account.
Display your company name as the Developer on the App Store (e.g., Business Inc. instead of an individual name).
Apple recognizes you as an authorized representative, avoiding brand or content disputes.
Next Steps: Registering for an Apple Developer Account
Once you have your Apple Account and (if applicable) your DUNS Number, go to https://developer.apple.com/programs/enroll/ and click the “Start your enrollment” button.
Fill out the required forms with accurate information. Once completed, you should receive an email confirming your enrollment. Apple will then review your submission, which may take up to 3 business days.
The Apple Developer Program costs $99 per year and must remain active to keep your app available on the App Store. At the end of the enrollment process, you will be prompted to complete the payment—be sure to finalize the payment to complete your registration.
Oops! Something went wrong while submitting the form.
This snippet detects if a visitor is on iOS or Android and automatically redirects them to the correct app store.
How it Works
This guide will help you create a smart redirect page that automatically sends your visitors to the correct app store (Google Play or Apple App Store), depending on their device.
You do not need to be a developer to use this, we’ve written this guide to walk you through the steps, even if you have very limited experience editing code.
Creating a custom redirect page on your own website gives you full control over the download experience — and unlocks key benefits for your marketing and analytics efforts.
What Is This For?
Many platforms and ad tools limit your visibility when you send users directly to the App Store or Play Store. By creating a simple redirect page on your own domain, you solve two major problems:
Branded Experience You own the page (e.g. yourdomain.com/stores-redirect), so users see your domain in all marketing materials — not a third-party link. This builds trust and improves click-through rates, especially on QR codes and paid ads.
Track Everything Since the redirect page lives on your website, you can add Google Analytics, Meta Pixel, UTM tags, or any other tracking tool — giving you complete visibility into how users are arriving and where they go next. This is essential for campaign measurement and A/B testing.
This approach is ideal for customers who want more control, deeper insights, and a seamless experience across web and app.
The URL should look like this, where the app store links are passed as URL parameters:
If you’re using a CMS (like Shopify, Webflow, Squarespace, or WordPress), look for a way to add a new page and edit the HTML content directly. You should be able to paste in the code provided below.
You’ll find specific guides for each at the bottom of this page
Option 1: Automatic Redirect (JavaScript Only)
Best for: Users should be taken to the correct store instantly, without seeing any message or UI.
How to use:
Paste the JavaScript snippet (see below) right before
on your page.
That’s it — users are redirected as soon as they land on the page.
Click the “Show HTML” button () in the editor toolbar
Paste the full HTML + JavaScript code provided (Option 1 or 2)
Click Save
Your redirect page will be available at a URL like https://yourstore.com/pages/stores-redirect
WordPress (Classic Editor or Gutenberg)
Option A: Using a Custom Page
In WordPress admin, go to Pages > Add New
Title your page: stores-edirect
In the editor, switch to Text/HTML view (Classic Editor) or use a Custom HTML block (Gutenberg)
Paste the full code (Option 1 or 2)
Click Publish
Option B: Using a Plugin (for advanced users)
You can use plugins like Insert Headers and Footers or WPCode to insert JavaScript into your site if needed.
Webflow
In your Webflow Dashboard, open your project
Go to Pages and click “+ New Page”
Name it something like stores-redirect
Open the Page Settings
Scroll to Before tag and paste the JavaScript snippet
Use a Custom Code Embed block at the top of your page to paste the HTML + CSS (for Option 2)
Save and publish
✅ Make sure “Custom Code” is enabled in your site settings (requires paid plan).
Squarespace
Squarespace doesn’t support full JavaScript execution in content blocks on all plans, so Option 2 (with fallback UI) is recommended only if your plan supports code injection.
Go to Pages > Add a new Blank Page
Name it something like stores-redirect
Open the Edit mode
Click “+” and choose “Code”
In the Code Block, paste the full HTML + JavaScript
Check “Display Source” OFF
Save the page
✅ Note: Full code blocks only work on Business or Commerce plans.
1. Swipe down from the top of your screen.2. Tap the “Screen record” icon ◦ You might need to swipe right to find it ◦ If it’s not there, tap Edit and drag Screen record to your Quick Settings3. Choose what you want to record and tap Start. The recording begins after the countdown4. To stop recording, swipe down from the top of the screen and tap the Screen recorder notification
The QR Code Widget allows you to promote app-specific features, and discounts, followed by a QR code that can be scanned to open your app install page on mobile devices.
What Are QR Widgets?
QR widgets are modals/popups that show up when someone lands on your desktop website, prompting them to get your app.
Here’s an example:
Features ✨
ML QR Widget features:
Configuration options:
Widget position
Widget delay
Texts fonts
Texts color
Widget BG
QR colors
QR with images
Text content
Entering animation
Display options: On load or when user scrolls up/down
Fallback options –> If the provided icon link is invalid / or image can not be displayed, an icon is generated using the App Name Param and Button colors
Default options set (if not texts, images or colors provided, it shows placeholder info, useful for catching errors or for testing while implementing the widgets)
Widget can be used as a module or used directly in an html / script tag
The library uses QuickChart’s QR Library, methods from their API are available to use within the widget
Code written in Typescript and minified/bundled with Vite
How to use 📖
QR Widget can be used importing the JS code via CDN or as a module using NPM
With CDN 🚀
In order to install the QR Code Widget you will want to add the following piece of code into your website, before closing tags:
scripttype="module"src="https://cdn.jsdelivr.net/npm/@vendrux/ml-qr-widget@latest/dist/ml-qr-widget.min.js">script>script>functionaddQrWidget() {
new QrWidget().init();
}
window.addEventListener('load', addQrWidget);
script>
const options = {
fontFamily: `"Source Sans Pro", "Arial", sans-serif`, // (string) Font family for widgets texts, defaults to system safe fontstextColor: '#222', // (string) Widget texts color (any color property value)textHeading: 'Get 10% OFF using Vendrux app', // (string) Heading TexttextDescription: 'Scan our QR to download the app on your device and unlock the discount', // (string) Description textwidgetsColor: '#fff', // (string) Widget BG colorbackDrop: true,// (boolean) if true, adds a backdop in front of the pagebackDropZIndex: 888888, // (number) z-index of the backdrop, should be lower than widgets z-indexqrOptions: { // Params for the QR Generation, uses params from this docs: https://quickchart.io/documentation/qr-codes/text: "https://redirect.vendrux.com/?ios=https://itunes.apple.com/",
size: 150,
margin: 0 },
position: 'center', // (string) Position of the widgets, default 'center'. 'center' | 'top-right' | 'top-left' | 'bottom-left' | 'bottom-right'animation: 'fadeIn', // (string) Widget animation, default 'fadeIn'. 'fadeIn' | 'scaleUp' | 'slideBottom' | 'slideTop' | 'slideLeft' | 'slideRight' | null,display: 'onLoad', // (string) Display options, default 'onLoad'. 'onLoad' | 'onScrollDown' | 'onScrollUp'radius: '10px', // (string) Widget radius with CSS unitsdelay: 0, // (number) defines how much time to wait until the element shows upshadow: true, // (boolean) If true applies soft shadow, true | falseuseSession: false, // (boolean) If true, after widgets is closed, it creates a session registry to hide widgets on page reloads until the end of user's sessionzindex: 999999, // (number) Widget z-indexmaxWidth: "400px", // (string) Max Width of the widgets with CSS unitssessionExpire: 1440// (number) time for banner to show again in minutes starting from the time the banner is shown, defualt: 1440 (1 day) };
const qrWidget = new QrWidget(options);
Methods 💡
deviceData.os // returns current os "android" | "ios" | "windows" | "desktop"deviceData.isCanvas // returns true or falsedeviceData.isMobile // returns true or false
Recipes 🍳
This are useful ways to implement the widget. We always recommend using an Event Listener to trigger the code when the document is loaded window.addEventListener('load', fnName)
const options = {
// Set params here}
// Insert widgets only in our Canvas platformif(deviceData.isCanvas) {
const qrWidget = new QrWidget(options);
}
// Apply specific configs based on OSif(deviceData.os === "android" || deviceData.os === "windows") {
const qrWidget = new QrWidget(options1); // different options sets can be passed for different platforms}
if(deviceData.os === "desktop" || deviceData.os === "ios") {
const qrWidget = new QrWidget(options2);
}
// Insert widgets only in Mobile userAgentif(deviceData.isMobile) {
const qrWidget = new QrWidget(options3);
}
How Banner Session works
When ‘useSession’ parameter is set to true, the banners appears once until the banner is closed, after closed, the banner won’t appear until the next day (default) or until the time configured in the ‘sessionExpire’ parameter, this parameter should have the time in minutes.
1. If user closes the modal, it creates a LocalStorage key called “widgetClosed” with a date value (for example if we set up the sessionExpire value to 1440 (minutes), it would hide until tomorrow)
2. On widget init(), the library checks if the param exists and if the date is bigger than current date
3. If the expiration date already passed, the key is removed from storage and widget is shown again
Redirect URL 🔗
We provide a custom redirect URL that sends users to the correct app store using a single link.
Yes! Note Apple’s and Google’s fees are not included in our pricing. The Apple App Store charges a US$99 annual developer fee and Google Play charges a one-time fee of US$25.
Yes, Vendrux can take care of the submission process for you.
Can I publish the apps on my own using the binaries?
Yes, we can send you binaries for your app and have you publish it, if you know what you’re doing. Just request so when completing Vendrux’s submission form.
You will still need to provide us with your Apple’s account credentials or add us as an Admin team member to your team (for Organisation accounts only). This is because we’ll need your account to sign the app for publishing.
Our Promotions Banner widget will allow you to display a message when your website gets displayed inside the apps, so you can provide exclusive app offers to your users.
Here’s an example:
Features ✨
ML Promotions Banner features:
Configuration options:
Banner position
Banner delay
Texts fonts
Texts color
Banner BG
Text content
Entering animation
Display options: On load or when user scrolls up/down
Android and iOS links
Button Link applies automatically depending on user agent: If Android, it uses the provided android link if iOS, uses the provided ios link.
deviceData method available: its a function that can be called to get the current browser OS, useful for triggering external functions’. It returns a string containing “android” | “ios” | “windows”
Default options set (if not texts, images or colors provided, it shows placeholder info, useful for catching errors or for testing while implementing the banner)
Banner can be used as a module or used directly in an html / script tag
Code written in Typescript and minified/bundled with Vite
How to use 📖
Promotions Banner can be used importing the JS code via CDN or as a module using NPM
With CDN 🚀
scripttype="module"src="https://cdn.jsdelivr.net/npm/@vendrux/ml-promotions-banner@latest/dist/ml-promotions-banner.min.js">script>script>functionaddPromotionsBanner() {
new PromotionsBanner().init();
}
window.addEventListener('load', addPromotionsBanner);
script>
const options = {
fontFamily: `"Source Sans Pro", "Arial", sans-serif`, // Font family for banner texts, defaults to system safe fontstextColor: '#222', // Banner texts color (any color property value),textHeading: 'Get a discount on your first purchase', // Heading TexttextDescription: 'Use coupon 10OFF', // Description textbannerColor: 'white', // Banner BG colorlink: '#', // Link for buttonposition: 'top', // Position of the banner, default 'top'. 'top' | 'bottom'animation: 'fadeIn', // Banner animation, default 'fadeIn'. 'fadeIn' | 'scaleUp' | 'slideBottom' | 'slideTop' | 'slideLeft' | 'slideRight' | null,display: 'onLoad', // Display options, default 'onLoad'. 'onLoad' | 'onScrollDown' | 'onScrollUp'radius: '0', // Banner radius with unitsdelay: 0, // defines how much time to wait until the element shows up in msshadow: true, // If true applies soft shadow, true | falseuseSession: false,
zindex: 9999999}
const promotionsBanner = new PromotionsBanner(options);
Methods 💡
deviceData.os // returns current os "android" | "ios" | "windows" | "desktop"deviceData.isCanvas // returns true or falsedeviceData.isMobile // returns true or false
Recipes 🍳
This are useful ways to implement the widget
const options = {
fontFamily: `"Source Sans Pro", "Arial", sans-serif`, // Font family for banner texts, defaults to system safe fontstextColor: '#222', // Banner texts color (any color property value),textHeading: 'Get a discount on your first purchase', // Heading TexttextDescription: 'Use coupon 10OFF', // Description textbannerColor: 'white', // Banner BG colorlink: '#', // Link for buttonposition: 'top', // Position of the banner, default 'top'. 'top' | 'bottom'animation: 'fadeIn', // Banner animation, default 'fadeIn'. 'fadeIn' | 'scaleUp' | 'slideBottom' | 'slideTop' | 'slideLeft' | 'slideRight' | null,display: 'onLoad', // Display options, default 'onLoad'. 'onLoad' | 'onScrollDown' | 'onScrollUp'radius: '0', // Banner radius with unitsdelay: 0, // defines how much time to wait until the element shows up in msshadow: true, // If true applies soft shadow, true | falseuseSession: false,
zindex: 9999999}
// Insert banner only in our Canvas platformif(deviceData.isCanvas) {
const promotionsBanner = new PromotionsBanner(options);
}
// Apply specific configs based on OSif(deviceData.os === "android" || deviceData.os === "windows") {
const promotionsBanner = new PromotionsBanner({link: 'https://linkOne.com'});
}
if(deviceData.os === "desktop" || deviceData.os === "ios") {
const promotionsBanner = new PromotionsBanner({link: 'https://linkTwo.com'});
}
// Insert banner only in Mobile userAgentif(deviceData.isMobile) {
const promotionsBanner = new PromotionsBanner(options);
}
Using a “copy text” function for coupons
// Set banner text with an onclick function in itconst options = {
textDescription: `Please use code 10OFF for 10% off in your next order!`}
// Create the copyBannerText function that is linked to the description text, it copies the text, displays a "Copied!" message in that place and then shows the passed text again functioncopyBannerText(e, text){
navigator.clipboard.writeText(text);
e.textContent = "Copied!"setTimeout( function() {
e.textContent = text
}, 3000);
}
functionaddPromotionsBanner() {
// Here we can use the deviceData method to display the banner only on desired devicesnew PromotionsBanner(options).init();
}
window.addEventListener('load', addPromotionsBanner);
The “Regex” parameter determines which URLs will trigger the printing. You will need to make sure that the URLs that should trigger the print feature match the regex code used.
If your URL looks like this: https://website.com/document?print=true
You can use the value displayed in our example, it will be a match because the URL contains “print” in it.