Docs
grovs.io Start for free

How smart banners behave

When a smart banner shows, which pages and devices it matches, how it hides after a close or a tap, what the button opens and what the stats count.

All plans, Cloud and self-hosted · Requires Web SDK 2.1.0

When a banner shows

The Web SDK shows a banner on a page when all of this holds:

  1. Grovs.configure() has run, banners aren't turned off with smartBanner: false, and, under requireConsent, consent was granted.
  2. The project has at least one live banner.
  3. The visitor is on a phone or tablet the banner targets (see Platforms).
  4. The page matches the banner's pages (see below).
  5. The visitor hasn't closed the banner or tapped its button recently (see Hiding).

When several banners pass, the one highest in the dashboard list wins. Only one banner shows at a time, even if two copies of the SDK run on the page.

Platforms

VisitorSees the banner
iPhone or iPad, in any browserWhen the banner targets iOS
Android phone or tablet, in any browserWhen the banner targets Android
Desktop browsersNever

Detection uses the browser's user agent. iPads that present themselves as a Mac are recognised by their touch screen.

The banner also shows inside web views, including your own app's. Pass smartBanner: false to configure() in your app's web views. Inside the built-in browsers of Instagram, Facebook and similar apps, the button may not be able to open your app.

Which pages show it

Paths in Only on pages and Except on pages are matched against the page's path:

  • Only the path counts. The query string and #anchor are ignored, so /shows/4815?ref=mail matches /shows/*.
  • * matches any run of characters, including /, so /shows/* matches /shows/4815/episodes. Everything else is literal.
  • Matching ignores letter case and a trailing /, and decodes the path, so /Shows/ matches /shows.
  • With Show on all pages, every page matches. A page that matches Except on pages never shows the banner.

Hash-routed sites. When the URL's hash starts with #/ or #!/, as in shop.com/#/product/42, the hash is the path: /product/42. An app mounted under a path (/app/#/product/42) matches on the hash route alone, so write /product/*, not /app/product/*. Other hashes, such as #reviews, are plain anchors.

Single-page apps. The SDK follows route changes on its own (pushState, replaceState, back and forward, hash changes), whatever your screen-tracking settings. A new path is a new page: the banner is chosen again, the link data you set is cleared, and a Until the next page hide ends. A change to only the query string or the anchor is the same page.

What the button opens

The button is a Grovs link:

  • App installed: the app opens and receives the link's data.
  • Not installed: the visitor goes to the App Store or Google Play. After install, your app receives the link's data on first open.

On pages where you called setLinkData(), the link carries that data plus page_path; elsewhere it's the banner's default link, with no page data. A tap before the page's link has arrived uses the default link. The link opens in the same tab and never shows a preview page.

Banner links don't credit a referrer, and they're kept out of your links list, per-link metrics and CSV exports. They still count in your project's totals. They can't be edited or deleted as ordinary links, and they keep working after the banner is deleted.

Each banner hands out at most 10,000 different page links. After that, pages get the default link.

Hiding after a close or a tap

The visitorHidden forDefault
Taps ×When a visitor closes it7 days
Taps the buttonWhen a visitor taps Open30 days

Until the next page (0 days) hides it only until the visitor moves to another page.

Hiding is per banner: closing one doesn't hide another that targets other pages. It's stored in the browser's local storage, so it applies to that browser and device only. Clearing site data brings the banner back. Grovs.smartBanner.hide() hides the banner on the current page without counting as a close.

"Open" means the tap. The SDK can't tell whether the app actually opened.

How it looks

  • Top banners are placed at the top of the page and push it down. They scroll away with the page.
  • Bottom banners are fixed to the bottom of the screen, above the page and clear of the home indicator.

The banner is drawn in its own shadow DOM, so your site's CSS doesn't change it and its CSS doesn't leak into your page. It works under a Content-Security-Policy that restricts styles. Title and subtitle are each one line, cut short with an ellipsis when too long. Colours are the ones you set; the banner doesn't switch for dark mode.

The button is an ordinary link, and the close button is labelled "Close" for screen readers.

What's counted

The SDK sends three events with the banner's id:

EventWhen
smart_banner_viewOnce per page view per banner, when it shows
smart_banner_clickA tap on the button
smart_banner_dismissA tap on ×

The dashboard shows each banner's last 30 days:

StatMeans
Views, Clicks, DismissesCounts of the three events
CTRClicks divided by views
Dismiss rateDismisses divided by views
InstallsInstalls and reinstalls that came through the banner's links, the default link and every page link

Updates and failures

The list of banners is cached for 10 minutes, on the server and in the visitor's browser tab, so a change in the dashboard reaches visitors within about 10 minutes.

If a request fails, the SDK waits 60 seconds, or longer if the server asks it to, before trying again, across page loads in the same tab. A banner already showing stays.

Last updated 2026-10-26
Was this page helpful?