This tutorial walks through adding Tolinku smart banners to a web project from scratch. It is written for developers doing the actual integration, so it covers the specifics: the exact configuration options, how the customization API works, what events you can listen to, and how to verify things are working correctly before going to production.
If you are evaluating whether Tolinku banners fit your use case, the smart banners feature page has the higher-level overview. This tutorial assumes you have already made that decision and are ready to ship.
Prerequisites
- A Tolinku account with an Appspace created for your app
- Your Tolinku publishable API key (
tolk_pub_...) - An iOS or Android app published on the App Store or Google Play
- A web project where you can add a script tag or npm package
If you have not set up your Appspace yet, the Tolinku smart banners documentation covers the dashboard configuration steps that precede the code integration.
Installation
There are two ways to load the Tolinku Web SDK: via a script tag, or via npm. Use npm if you are working in a bundled JavaScript application (React, Vue, SvelteKit, Next.js, etc.). Use the script tag for WordPress sites, plain HTML, or any situation where you do not have a JavaScript build step.
Option 1: Script Tag
Add the following to the <head> of your HTML, before the closing </head> tag:
<script
async
src="https://cdn.tolinku.com/banner.js"
data-tolk-key="tolk_pub_your_key_here"
data-tolk-app-id="your_appspace_id"
></script>
Using async ensures the script does not block HTML parsing. The banner will initialize after the DOM is ready.
For sites where you want to minimize impact on initial page load, defer is an alternative:
<script
defer
src="https://cdn.tolinku.com/banner.js"
data-tolk-key="tolk_pub_your_key_here"
data-tolk-app-id="your_appspace_id"
></script>
defer guarantees execution order (scripts with defer run in order after HTML parsing completes), while async does not. Use defer if you have other scripts that depend on the banner SDK being available.
Option 2: npm
npm install @tolinku/web-sdk
Then in your application entry point:
import { Tolinku } from '@tolinku/web-sdk';
const tolinku = new Tolinku({
key: 'tolk_pub_your_key_here',
appId: 'your_appspace_id',
});
tolinku.init();
For TypeScript projects, the SDK ships with type definitions:
import { Tolinku, TolinkuConfig } from '@tolinku/web-sdk';
const config: TolinkuConfig = {
key: 'tolk_pub_your_key_here',
appId: 'your_appspace_id',
};
const tolinku = new Tolinku(config);
tolinku.init();
The full Web SDK documentation covers the complete TypeScript interface.
Basic Configuration

After initialization, the SDK reads your Appspace's banner configuration from the Tolinku API and renders the banner according to the rules you have set in the dashboard. The minimum configuration (key + appId) is sufficient to get a working banner with your dashboard settings.
For more control at the code level, the Tolinku constructor accepts a full configuration object:
const tolinku = new Tolinku({
key: 'tolk_pub_your_key_here',
appId: 'your_appspace_id',
// Banner display options
banner: {
position: 'top', // 'top' or 'bottom'
showDelay: 0, // milliseconds before showing (0 = immediate)
scrollTrigger: 0, // show after N pixels scrolled (0 = disabled)
sessionCap: 1, // max impressions per session
dismissalTtl: 604800, // seconds before showing again after dismiss (7 days)
},
// Deep link configuration
deepLink: {
useCurrentUrl: true, // pass current page URL as deep link context
customParams: {}, // additional params to pass through
},
});
All of these options have defaults that match the recommended settings for most implementations. You typically only need to override what differs from the defaults.
Position
'top' renders the banner at the top of the viewport as a fixed bar. 'bottom' renders it at the bottom. The top position is more visible; the bottom position is less disruptive to reading. Default is 'top'.
showDelay
Milliseconds to wait after page load before rendering the banner. A value of 1000-2000ms means the user can confirm they have landed on useful content before seeing the prompt. For pages with significant organic search traffic, a small delay is a reasonable courtesy. Default is 0.
scrollTrigger
If set to a positive number, the banner only appears after the user has scrolled at least that many pixels. scrollTrigger: 300 means the banner appears after a typical mobile scroll. This is mutually exclusive with showDelay in most use cases; pick one. Default is 0 (disabled).
sessionCap
Maximum number of times the banner is shown within a single browser session. Setting this to 1 means users see the banner at most once per session, even if they navigate to multiple pages. Default is 1.
dismissalTtl
After a user dismisses the banner, how many seconds before it shows again. The default is 604800 (7 days). Set to 0 to suppress the banner permanently once dismissed (stored in localStorage). Set to a lower value for high-traffic sites where you expect a lot of new visitors.
Customization API

The configuration object covers structural options, but visual customization is handled through CSS custom properties (CSS variables). The Tolinku banner injects a <div class="tolk-banner"> element into the DOM and uses a defined set of CSS variables for theming.
You can override any of these in your stylesheet:
:root {
--tolk-banner-bg: #1a1a2e;
--tolk-banner-text: #ffffff;
--tolk-banner-cta-bg: #4f46e5;
--tolk-banner-cta-text: #ffffff;
--tolk-banner-height: 80px;
--tolk-banner-font-family: inherit;
--tolk-banner-border-radius: 0px;
--tolk-banner-app-icon-size: 48px;
}
The inherit value on font-family means the banner picks up your site's typeface automatically, which is usually what you want for a cohesive look.
For the app icon, the SDK fetches it from the App Store or Google Play automatically using the app identifiers in your Appspace configuration. You do not need to host the icon yourself.
Custom message text
To override the banner message at the code level (rather than in the dashboard), use the message option:
const tolinku = new Tolinku({
key: 'tolk_pub_your_key_here',
appId: 'your_appspace_id',
banner: {
message: 'Get the full experience in the app',
ctaText: 'Open App',
},
});
For dynamic messages based on page content, you can read from the DOM before initializing:
const productName = document.querySelector('[data-product-name]')?.textContent;
const tolinku = new Tolinku({
key: 'tolk_pub_your_key_here',
appId: 'your_appspace_id',
banner: {
message: productName
? `See ${productName} in the app`
: 'Get the full experience in the app',
ctaText: 'Open App',
},
});
The designing smart banners guide covers all the visual customization options available from the dashboard, which are more extensive than the CSS variable approach.
Event Callbacks
The SDK emits events at key points in the banner lifecycle. You can listen to these to integrate banner behavior with your analytics, A/B testing, or other systems.
const tolinku = new Tolinku({
key: 'tolk_pub_your_key_here',
appId: 'your_appspace_id',
});
// Banner became visible
tolinku.on('banner:shown', (data) => {
console.log('Banner shown', data);
// Send to your analytics
analytics.track('App Banner Shown', {
page: window.location.pathname,
variant: data.variant,
});
});
// User tapped the CTA button
tolinku.on('banner:clicked', (data) => {
console.log('Banner clicked', data);
analytics.track('App Banner Clicked', {
page: window.location.pathname,
destination: data.destination, // 'app_store' | 'app_open' | 'play_store'
});
});
// User tapped the dismiss button
tolinku.on('banner:dismissed', () => {
analytics.track('App Banner Dismissed', {
page: window.location.pathname,
});
});
// Banner was not shown (and why)
tolinku.on('banner:suppressed', (reason) => {
console.log('Banner suppressed:', reason);
// reason values: 'session_cap', 'dismissed_recently', 'app_installed', 'platform_unsupported'
});
tolinku.init();
Note that tolinku.on() calls must be made before tolinku.init(). Events emitted before listeners are registered are not replayed.
Available events
| Event | Description | Data |
|---|---|---|
banner:shown |
Banner is rendered and visible | { variant, platform } |
banner:clicked |
CTA button tapped | { destination, deepLinkUrl } |
banner:dismissed |
Dismiss button tapped | none |
banner:suppressed |
Banner would have shown but was suppressed | reason: string |
deeplink:resolved |
Deep link URL was generated | { url } |
Programmatic Control
For single-page applications where route changes do not trigger a full page reload, you may want to control when the banner is shown or update its content on navigation.
// Manually trigger banner show
tolinku.showBanner();
// Manually hide without dismissal (does not set dismissal cookie)
tolinku.hideBanner();
// Update banner message for the current page
tolinku.updateBanner({
message: 'New message for this page',
deepLinkUrl: 'https://yourdomain.com/current-page',
});
// Check current state
const state = tolinku.getBannerState();
// { visible: boolean, dismissed: boolean, suppressed: boolean }
For React applications, a common pattern is to call updateBanner() inside a useEffect on route change:
import { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
function AppBannerUpdater({ tolinku }) {
const location = useLocation();
useEffect(() => {
tolinku.updateBanner({
deepLinkUrl: window.location.href,
});
}, [location.pathname]);
return null;
}
Testing Your Integration
Before deploying to production, verify the integration with these steps.
1. Confirm the script is loading
Open browser DevTools, go to the Network tab, and filter for banner.js or your npm bundle. Confirm the request completes with a 200 status and no console errors.
2. Verify the banner renders
With the SDK loaded, the banner should appear according to your trigger configuration. If showDelay is 0 and scrollTrigger is 0, it should appear immediately. Check the Elements tab for a .tolk-banner element in the DOM.
If the banner does not appear, check:
- Is the API key correct?
- Is the Appspace ID correct?
- Is the Appspace configured with at least one banner in the dashboard?
- Are there any console errors?
3. Test on both iOS and Android
The banner behavior differs slightly between platforms. On iOS, the banner detects whether the app is installed (where possible via Safari's universal link behavior) and adjusts the CTA accordingly. On Android, the detection mechanism is different. Test on real devices or in Chrome DevTools with device emulation set to iPhone and Android Pixel modes.
4. Verify deep link behavior
Tap the banner CTA. On a device with the app installed, confirm the app opens to the correct screen. On a device without the app installed, confirm the App Store or Google Play opens to the correct app listing.
If you have deferred deep linking configured, the full test requires installing the app after tapping the banner and verifying the app opens to the expected content. This cannot be fully tested in a simulator; it requires a real device without the app installed.
5. Test dismissal and session cap
Dismiss the banner and refresh the page. The banner should not reappear within the dismissalTtl window. Open a new browser tab (new session) and the banner should appear again (up to the sessionCap).
To reset dismissal state during development without waiting for the TTL to expire:
// In the browser console
localStorage.removeItem('tolk_banner_dismissed');
sessionStorage.removeItem('tolk_session_count');
6. Measure CLS impact
Use Chrome DevTools' Performance panel or PageSpeed Insights to check CLS before and after adding the banner. If CLS increased, the banner injection is causing layout shifts. See the smart banners and SEO guide for remediation.
Deployment Checklist
- API key is the publishable key (
tolk_pub_...), not the secret key - Script is loaded with
asyncordefer -
sessionCapanddismissalTtlare set appropriately - Banner appears correctly on both iOS and Android
- Deep links route to the correct app screen
- CLS impact has been measured and is acceptable
- Event callbacks are connected to your analytics system
- Banner is not visible to users who already have the app installed (or shows an "Open" prompt instead)
Get deep linking tips in your inbox
One email per week. No spam.