Skip to content

Triggers

A trigger decides when a popup shows. The trigger is configured by your team in Deepdots and delivered to the SDK automatically — you never write trigger definitions in code.

However, depending on the trigger type, your application may need to do something so the trigger can actually fire: render an element with a specific id, emit a custom business event, etc. This page explains each type and shows the host-side code required.

TypeFires when…Value semantics
time_on_pageThe user has been on a page for N seconds.numberseconds on page
scrollThe user has scrolled N% of the page height.number — percentage 0–100
clickThe user clicks an element with a specific DOM id.string — the element’s id attribute
exitThe user navigates away from the current route.numberseconds of delay on the next route
eventYour application calls popups.triggerEvent(name).string — the event name

Fires after the user has spent a number of seconds on the page.

Host-side code: none. As long as the SDK has been initialized and autoLaunch() was called, the SDK starts the timer when the page loads.

import { DeepdotsPopups } from '@magicfeedback/popup-sdk';
const popups = new DeepdotsPopups();
popups.init({ mode: 'server', apiKey: 'YOUR_PUBLIC_API_KEY' });
popups.autoLaunch();
// Time triggers configured in Deepdots will now fire on their own.

Fires when the user has scrolled past a given percentage of the page height.

Host-side code: none. The SDK attaches its own scroll listener and removes it once the threshold is reached.

popups.init({ mode: 'server', apiKey: 'YOUR_PUBLIC_API_KEY' });
popups.autoLaunch();
// A scroll trigger configured at 70% in Deepdots fires automatically
// when the user reaches 70% of the page.

Fires when the user clicks a DOM element with a specific id.

Host-side code: your application must render an element whose id matches the value configured in Deepdots.

<!-- Any element with the configured id will trigger the popup -->
<button id="feedback-btn">Give feedback</button>

Or, in a framework:

// React
<button id="feedback-btn" onClick={handleClick}>
Give feedback
</button>

The SDK attaches a one-shot click listener to the element. Once it fires, the listener is removed automatically.


Queues a popup to appear on the next route after the user leaves the current one. Useful for “before you go” surveys without blocking navigation.

Host-side code: none for standard SPA navigation. The SDK monkey-patches history.pushState / history.replaceState and listens to popstate, hashchange, and same-origin link clicks. Any normal client-side route change is detected.

popups.init({ mode: 'server', apiKey: 'YOUR_PUBLIC_API_KEY' });
popups.autoLaunch();
// When the user navigates away from a targeted route,
// the popup is queued and shown on the next route after the configured delay.

How it works in practice:

  1. The user is on /pricing (where an exit trigger is targeted).
  2. The user clicks a link to /features.
  3. The SDK queues the popup in sessionStorage.
  4. On /features, after the delay configured in Deepdots, the popup appears.

Fires when your application emits a custom business event by name. This is the trigger type you will use most often in code.

Host-side code: call popups.triggerEvent(eventName) whenever the business condition is met. The event name must match exactly the value configured for the trigger in Deepdots.

import { DeepdotsPopups } from '@magicfeedback/popup-sdk';
const popups = new DeepdotsPopups();
popups.init({ mode: 'server', apiKey: 'YOUR_PUBLIC_API_KEY' });
popups.autoLaunch();
// Later, when something interesting happens in your app:
function onCheckoutCompleted() {
popups.triggerEvent('checkout_completed');
}
function onSearchAttempted(query: string) {
if (searchAttempts >= 3) {
popups.triggerEvent('search_no_results');
}
}
function CheckoutButton({ popups }: { popups: DeepdotsPopups }) {
return (
<button
onClick={async () => {
await placeOrder();
popups.triggerEvent('checkout_completed');
}}
>
Pay
</button>
);
}
async function submitContactForm(data) {
const ok = await api.submit(data);
if (ok) {
popups.triggerEvent('contact_form_sent');
}
}

A popup in Deepdots can have more than one trigger. Any of them firing will show the popup (subject to cooldowns and route targeting). For example: a popup might be configured to fire after 30 seconds or when the user emits cart_abandoned, whichever happens first.

You don’t need to do anything special in code — just make sure your application provides the right host signals (mounting the click target id, calling triggerEvent, etc.) for every trigger type the popup uses.


Manually showing a popup outside any trigger

Section titled “Manually showing a popup outside any trigger”

If you need to bypass triggers entirely — for example, a “Feedback” button always available in the footer — call show() or showByPopupId() directly:

popups.show({
surveyId: 'survey-feedback-001',
productId: 'product-main',
});
// Or, if you know the popup id from Deepdots:
popups.showByPopupId('popup-footer-feedback');

Cooldowns and route targeting are still respected.