Docs

Install guide

Getting a popup live takes one script tag. Here's the whole process, plus platform notes and troubleshooting.

1

Analyze or choose a template

Start with the website analyzer to create a brand kit, or open a design directly from the template library.

2

Publish it

A popup only renders on your site once its status is published. Drafts and paused popups are intentionally invisible to visitors.

3

Copy your snippet

Click Embed in the builder to get the snippet containing your own data-popup-id. Every popup has a unique ID.

4

Paste it into your site

Add it once, just before the closing </body> tag. After that, edits you make in the builder go live without touching your site again.

The snippet

What you're pasting

Replace the domain with your Bonpopup host and the popup ID with your own.

<!-- Bon Popup Code starts -->
<script async src="https://yourdomain.com/popup.js" data-popup-id="popup_101"></script>
<!-- Bon Popup Code Ends -->

Attributes

  • src — the popup engine script, served from your Bonpopup host at /popup.js.
  • data-popup-id — required. The public ID of the popup to render, e.g. popup_101. Without it the script exits quietly.
  • async — recommended, so the script never blocks rendering.

By platform

Where to paste it

The tag is the same everywhere. Only the place you put it changes.

Plain HTML / Popup ID

Paste directly before the closing </body> tag.

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>My site</title>
  </head>
  <body>
    <!-- your page content -->

    <!-- Bon Popup Code starts -->
    <script async src="https://yourdomain.com/popup.js" data-popup-id="popup_101"></script>
    <!-- Bon Popup Code Ends -->
  </body>
</html>

WordPress

  1. Open Appearance → Theme File Editor and select footer.php, or use a header/footer scripts plugin.
  2. Paste the snippet immediately before </body>.
  3. Save, then hard-refresh your site and clear any page cache.

On a block theme without footer.php, a footer-scripts plugin is the safer route than editing templates.

Shopify

  1. Go to Online Store → Themes → Edit code.
  2. Open layout/theme.liquid.
  3. Paste the snippet just before </body> and save.

It applies across every page that uses that layout, including product and cart pages.

React / Next.js

Use the framework's script component so it loads after hydration.

import Script from "next/script";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}
        <Script
          src="https://yourdomain.com/popup.js"
          data-popup-id="popup_101"
          strategy="afterInteractive"
        />
      </body>
    </html>
  );
}

Advanced features

Beyond the basics

These features configure themselves inside the builder. Here's how they work at a glance.

Display modes

Choose in Appearance → Display mode:

  • Modal popup — centered overlay with backdrop. The default.
  • Notification bar — slim fixed bar at the top or bottom. No overlay, no card.
  • Embedded inline — renders inside a page element at a CSS selector you specify (e.g. #offer-slot). No floating behavior.

Countdown timer

  • Fixed deadline — counts down to a specific date/time. When it hits zero, hides the popup or shows expired text.
  • Evergreen — each visitor gets their own timer (stored in sessionStorage). Great for “next 60 minutes” offers that feel personal.

Configure in Content → Countdown timer.

Spin-to-win wheel

Replaces the standard CTA with a canvas-drawn prize wheel. Set 2–8 segments with labels, coupon codes, and probability weights. The spin is animated and the result fires a conversion event.

Configure in Content → Gamification wheel.

Multi-step flow

Add up to 5 follow-up screens after the initial CTA click. Each step has its own heading, description, and action (advance / open link / close).

Use cases: onboarding surveys, progressive disclosure, qualification funnels.

Configure in Content → Multi-step flow.

Dynamic text placeholders

Insert {{placeholder}} in any text field. Resolved at runtime per visitor:

  • {{page_path}}, {{page_title}}, {{domain}}
  • {{visitor_type}} (new/returning), {{traffic_source}} (direct/search/social/referral)
  • {{day_of_week}}, {{month}}, {{date}}, {{year}}
  • {{utm_source}}, {{utm_medium}}, {{utm_campaign}}

Example: Welcome, {{visitor_type}} visitor! Happy {{day_of_week}}.

Teaser tab

A small floating pill that stays on the page. Can appear before the trigger fires (as an alternative entry point) and/or after the popup is dismissed (so visitors can reopen it).

Configure in Behaviour → Teaser tab.

Social proof bar

A testimonial quote or activity counter shown below the CTA. Optional 1–5 star rating. Configure in Content → Social proof.

Conversion goal tracking

Set a goal URL path (like /thank-you) in Targeting → Conversion goal. A conversion event fires automatically when a visitor who saw the popup navigates to that page — no custom code needed.

A/B experiments

Enable in the builder sidebar. Traffic is split between Control A and Variant B using a sticky visitor hash. Analytics shows per-arm impressions, clicks, conversions, and uplift. Promote the winner with one click.

Campaign scheduling

Set optional start and end dates in Behaviour. The popup auto-activates and auto-expires without manual publish/pause. The embed script receives active: false outside the window.

Embedded mode setup

To use embedded mode, add a container element on your page:

<div id="popup-container"></div>

Then set #popup-container as the CSS selector in Appearance → Display mode → Embedded inline. The popup content renders inside that div.

Troubleshooting

Common questions

The popup isn't showing up at all

Work through these in order:

  • Confirm the popup status is published, not draft or paused.
  • Check the data-popup-id matches your popup exactly.
  • If you set a domain allowlist, make sure the current domain is on it. An empty allowlist means any domain is allowed.
  • Open your browser console and confirm popup.js returns 200 rather than 404.
  • Remember the trigger — a 5 second delay or exit-intent rule means it will not appear instantly.
  • If you set a schedule, confirm the current time is within the start/end window.
Can I add more than one popup to a page?

Add a separate script tag per popup ID. Each tag manages its own popup independently.

Does it work on localhost?

Yes. Point the script src at your running instance and leave the domain allowlist empty while testing.

Will it slow my page down?

The tag is async and the popup config is fetched separately after load, so it never blocks first render.

How do I stop a popup without removing the script?

Set its status to paused in the builder. The script stays in place and renders nothing until you publish again. You can also use scheduling to auto-expire.

Where do I see whether it's converting?

Each popup has an analytics page showing impressions, CTA clicks, conversions, audience breakdowns, and A/B experiment results.

How does the evergreen countdown work?

It stores the timer start in the visitor's sessionStorage. Refreshing the page doesn't reset it. A new browser session starts a fresh timer.

Can I test dynamic text without publishing?

Dynamic text resolves client-side, so you'll see the raw {{placeholders}} in the builder preview. Publish to a test domain to see them resolve with real visitor data.

What happens when an A/B experiment run changes?

A new run ID is created, and visitors are re-randomized. Old run data remains in analytics under the historical run selector.

Need a hand getting it live?

Send us the page you're embedding on and we'll take a look.

We usually reply within one business day.