Smart Banner Script
The smart banner script (banner.js) is a standalone embed for showing app install banners on customer websites. No npm install, no build step, just a script tag. It is the simplest way to add a smart banner to a marketing site, blog, or static page.
For programmatic control inside an SPA or framework, use the Web SDK instead.
Quick start
Section titled “Quick start”<script src="https://your-app.tolinku.com/banner.js" async></script>Replace your-app.tolinku.com with your Appspace’s domain. The script auto-detects iOS and Android devices, fetches your active banner config, and renders the highest-priority banner. Desktop visitors are ignored.
Configuration
Section titled “Configuration”Every option is set as a data-* attribute on the script tag. All attributes are optional. When omitted, sensible defaults are used.
Behavior
Section titled “Behavior”| Attribute | Values | Default | Description |
|---|---|---|---|
data-position | top, bottom | server config or top | Banner edge |
data-style | pinned, floating, stacked | pinned | Pinned (fixed overlay), floating (rounded fixed card), or stacked (sticky in document flow above the page header) |
data-anchor | CSS selector | (auto-detect) | Stacked mode only: explicit element to inject before. Auto-detects header, nav, [role="banner"], .header, #header, .navbar when omitted |
data-animation | slide, fade, pop, none | slide | Entrance animation |
data-theme | light, dark | light | Color preset (overridden by dashboard config) |
data-label | string | (any) | Show only banners with this label |
data-delay | 0–60000 | 0 | Delay display by N milliseconds |
Banner shape
Section titled “Banner shape”| Attribute | Values | Description |
|---|---|---|
data-bg | hex color | Banner background |
data-border | hex color | Border color (omit for none) |
data-radius | 0–24 | Banner corner radius (floating only) |
data-margin | 0–24 | Edge margin in pixels (floating only) |
data-shadow | none, sm, md, lg | Shadow preset |
Title (heading)
Section titled “Title (heading)”| Attribute | Values | Description |
|---|---|---|
data-title-color | hex color | |
data-title-size | 10–24 | Pixels |
data-title-weight | 400, 500, 600, 700 |
Body (description)
Section titled “Body (description)”| Attribute | Values | Description |
|---|---|---|
data-body-color | hex color | |
data-body-size | 10–20 | Pixels |
data-body-weight | 400, 500, 600, 700 |
CTA button
Section titled “CTA button”| Attribute | Values | Description |
|---|---|---|
data-cta-bg | hex color | Defaults to title color (auto-invert) |
data-cta-color | hex color | Defaults to banner background (auto-invert) |
data-cta-size | 10–18 | Pixels |
data-cta-weight | 400, 500, 600, 700 | |
data-cta-radius | 0–100 | 0 = square, 100 = pill |
| Attribute | Values | Description |
|---|---|---|
data-icon-size | 24–64 | Pixels |
data-icon-radius | 0–32 | Pixels |
Toggles
Section titled “Toggles”Boolean attributes. Add the attribute to enable; omit to disable.
| Attribute | Effect |
|---|---|
data-hide-icon | Hide the app icon |
data-hide-close | Hide the close button (banner cannot be dismissed) |
data-hide-body | Hide the description line, show only the title |
Custom CSS hook
Section titled “Custom CSS hook”| Attribute | Description |
|---|---|
data-class | Adds the value as a class on the banner container, so you can target it with your site’s CSS for advanced styling |
Examples
Section titled “Examples”Default pinned banner
Section titled “Default pinned banner”<script src="https://your-app.tolinku.com/banner.js" async></script>Floating dark banner with pop animation
Section titled “Floating dark banner with pop animation”<script src="https://your-app.tolinku.com/banner.js" data-style="floating" data-theme="dark" data-animation="pop" async></script>Custom-branded floating banner
Section titled “Custom-branded floating banner”<script src="https://your-app.tolinku.com/banner.js" data-style="floating" data-bg="#3B82F6" data-title-color="#ffffff" data-body-color="#dbeafe" data-cta-bg="#ffffff" data-cta-color="#3B82F6" data-radius="16" data-shadow="lg" async></script>Minimal one-line banner
Section titled “Minimal one-line banner”<script src="https://your-app.tolinku.com/banner.js" data-hide-body data-hide-icon data-style="floating" async></script>Bottom slide-in with 2 second delay
Section titled “Bottom slide-in with 2 second delay”<script src="https://your-app.tolinku.com/banner.js" data-position="bottom" data-delay="2000" async></script>How values are resolved
Section titled “How values are resolved”Every styling value resolves through this chain. The first non-empty source wins:
- The
data-*attribute on the script tag - The banner config set in your Tolinku dashboard
- The active theme’s value
- A built-in fallback
So a data-bg="#000" on the script tag overrides whatever color you set in the dashboard, which overrides whatever the theme would have provided, which overrides the built-in white.
Pinned vs floating vs stacked
Section titled “Pinned vs floating vs stacked”| Pinned | Floating | Stacked | |
|---|---|---|---|
| Position | position: fixed viewport overlay | position: fixed viewport overlay | position: sticky in document flow |
| Edges | Edge-to-edge across the viewport | Margin from each edge | Edge-to-edge |
| Corners | Square | Rounded (configurable) | Square |
| Layout impact | Pushes body content down via padding | Overlays content (no body push) | In flow, naturally pushes the page header down |
| Plays nicely with the host site’s fixed header? | No, overlaps it | No, overlaps it | Yes, the host header gets pushed down |
data-radius / data-margin | Ignored | Used | Ignored |
When to use each
Section titled “When to use each”- Pinned: simple sites without a fixed header. The banner overlays the very top of the viewport.
- Floating: marketing pages or hero sections where the rounded card aesthetic fits.
- Stacked: any site that already has its own fixed or sticky header. Stacked injects the banner above that header in the DOM so it doesn’t overlap navigation.
Stacked mode
Section titled “Stacked mode”When data-style="stacked", the script injects the banner element into the page DOM as a sibling of (and above) the host site’s header element. The banner uses position: sticky; top: 0 so it stays at the top of the viewport while the user scrolls.
Anchor detection
Section titled “Anchor detection”The script tries the following in order, using the first match it finds:
- The
data-anchor="<selector>"attribute, if provided. - The first
<header>,[role="banner"],<nav>,.header,#header, or.navbarin the document. - Falls back to inserting as the first child of
<body>.
For data-position="bottom", the same logic applies but with <footer>, [role="contentinfo"], .footer, #footer, and the banner is inserted after the anchor (or as the last child of <body>).
<!-- Auto-detect (most common) --><script src="https://your-app.tolinku.com/banner.js" data-style="stacked" async></script>
<!-- Explicit anchor when auto-detect picks the wrong element --><script src="https://your-app.tolinku.com/banner.js" data-style="stacked" data-anchor="#site-header" async></script>Caveat: the host site’s header is itself position: fixed
Section titled “Caveat: the host site’s header is itself position: fixed”If the host site’s header uses position: fixed; top: 0 (rather than position: sticky or no positioning), the banner can’t push it down via document flow because fixed elements are out of flow. The banner will sit above the header in the DOM but the header still renders at viewport top:0 over the banner area. The fix in that case is for the site to add its own offset — e.g. header { top: 56px; } while the banner is mounted, or to switch the header from fixed to sticky.
Caveat: the host site uses a custom scroll container
Section titled “Caveat: the host site uses a custom scroll container”position: sticky only works when the page scrolls on the document (the default). If the host site uses a wrapper div with overflow: auto as the scroll container (some app-style layouts), the banner sticks to the document, not to the wrapper, so it scrolls out of the wrapper’s viewport. Either switch to pinned/floating mode for those sites, or move the script tag inside the scroll container itself if your build allows.
Minor visual note: layout shift on insert
Section titled “Minor visual note: layout shift on insert”Because stacked mode injects an in-flow element, the page’s content shifts down by the banner height when the banner appears (and shifts back up when dismissed). The slide animation runs immediately after, so the perceived effect is “content shifts, banner slides in” with about a one-frame gap. Acceptable for a banner that loads on page open; if you need a perfectly smooth entrance, use floating instead, which overlays without reflowing.
Animation notes
Section titled “Animation notes”- slide is the safe default and works in both pinned and floating modes.
- fade and pop are best paired with
data-style="floating". In pinned mode,popsilently downgrades toslidebecause a center-origin scale clips visually against the viewport edge. - none removes both the entrance and exit transition. Use this when the banner needs to appear on a tightly-controlled UI (for example, inside an existing animation timeline).
Multi-banner sites
Section titled “Multi-banner sites”If you have multiple banners configured, use data-label to show a specific one on a specific page:
<!-- On the marketing homepage --><script src="..." data-label="website" async></script>
<!-- On a campaign landing page --><script src="..." data-label="promo" async></script>Without data-label, the highest-priority active banner is shown.
Dismissal
Section titled “Dismissal”When a visitor closes the banner, the dismissal is stored in localStorage for the number of days configured in the banner’s dismiss_days setting. Subsequent visits within that window will skip the banner and show the next one in the priority list.
Browser support
Section titled “Browser support”The script targets evergreen mobile browsers (Safari iOS 12+, Chrome Android 70+). It uses fetch, URL, URLSearchParams, localStorage, and requestAnimationFrame. The script returns early on desktop and on user agents it cannot match to iOS or Android, so there is no impact on desktop visitors.
Security
Section titled “Security”- All color values are sanitized (control characters and CSS-injection sequences are stripped) before being inserted into the rendered
<style>tag. - The CTA
hrefis validated to behttp:orhttps:only. Other protocols, includingjavascript:, are rejected. - The
data-classvalue is stripped to a safe character set ([a-zA-Z0-9_-\s], max 100 characters).
Compared to the Web SDK
Section titled “Compared to the Web SDK”| banner.js | @tolinku/web-sdk | |
|---|---|---|
| Install | <script> tag | npm install |
| Configuration | data-* attributes | Typed options object |
| When to use | Marketing sites, static pages, no build step | SPAs, frameworks, programmatic control |
| Bundle size | Single ~12 KB script | Tree-shakeable npm package |
| Banner features | Full v1.2 feature set | Same options as banner.js v1.2 |
The two paths render identical-looking banners. Pick whichever fits your stack.