JavaScript SDK
Everything the widget does is scriptable through window.Janus: open popups from your own buttons, jump steps, read and write flow variables, and listen for signups.
Methods
| Call | What it does |
|---|---|
Janus.open(campaignId, opts?) | Opens a campaign. If it's already armed on the page it opens instantly; otherwise the widget fetches it first. Options: { ignoreTargeting: true } to bypass audience rules (previews), { openStep: idOrIndex } to land on a specific step. A popup that's already open won't be interrupted. |
Janus.close() | Closes the active popup. |
Janus.step(idOrIndex) | Jumps the open popup to a step by id or index. |
Janus.refresh() | Re-evaluates which campaign matches (fresh cart, new URL, changed state) and re-arms triggers. Nothing pops instantly. |
Janus.vars.get(key) / Janus.vars.set(key, value) | Read/write session-scoped flow variables, the same store text variables and the Set variable(s) action use. |
Calling before the widget loads
The SDK absorbs a pre-init queue, so you never need to worry about script order:
window.Janus = window.Janus || [];
window.Janus.push({ type: 'open', campaignId: 42 });
The manual trigger
Give a campaign the Manual (SDK) trigger and it never auto-fires; it waits for your call. Perfect for "Get 10% off" buttons in your nav, mid-article links, or app-driven moments:
document.querySelector('#offer-button')
.addEventListener('click', () => Janus.open(42));
Events
A successful signup dispatches a DOM event on window:
window.addEventListener('popupstudio:signup', (e) => {
// fire pixels, open a chat, update UI…
});
For server-side needs, prefer the Klaviyo Popup Reward Issued event or the on-signup code hook, which receives the subscriber's details.
Embedded form mode
Render a campaign inline, no overlay and no trigger, by placing its container anywhere in your page:
<div id="ps_campaign_42"></div>
The widget mounts the campaign into the div on load. Embedded instances don't show teaser buttons and ignore frequency logic; they're part of the page. Grab the exact snippet from the builder under How it appears → Inside the page.
Preview URL parameters
| Parameter | Effect |
|---|---|
?ps_preview=ID | Load campaign ID for this visit only, regardless of status: the admin preview link. |
?embed=ID | On the demo sandbox: mount campaign ID inline for embed testing. |
What the widget stores
Visitor state lives in first-party localStorage keys prefixed ps_: session id, first-seen time, page/session counters, dismissals, conversion flag, variant assignment, teaser state and the claimed-code record. No third-party cookies, nothing cross-site. Clearing them resets the visitor, useful when testing:
Object.keys(localStorage)
.filter(k => k.startsWith('ps_'))
.forEach(k => localStorage.removeItem(k));
window.JanusCustomer; see installation.