> ## Documentation Index
> Fetch the complete documentation index at: https://docs.senderz.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Popup targeting and display

> Choose who sees a popup and when it shows itself: audience, URLs, country, UTM and cart rules, plus timing, frequency, schedule and custom triggers.

Every popup answers two separate questions. **Targeting** is who sees it. **Display** is when and how it shows itself. Both live behind the **Targeting and display** icon in the popup builder rail, split into a **Targeting** tab and a **Display** tab.

Nothing here changes what the popup looks like. For the builder itself, the step model and on-site install, see [Popups and forms](/en/messaging/popups).

<Info>
  Every rule on this page is evaluated in the visitor's browser against the live popup Senderz serves your storefront. Edits to a popup that is already live apply on the next page view, with no republish step.
</Info>

## Targeting: who sees the popup

### Audience

One choice, six options:

| Option                                         | Who sees the popup                                          |
| ---------------------------------------------- | ----------------------------------------------------------- |
| Show to all audience members                   | Everyone. This is the default when nothing is chosen.       |
| Don't show to existing profiles                | Only visitors Senderz does not already recognise.           |
| Show to any existing profile                   | Only visitors Senderz recognises, subscribed or not.        |
| Show to email only subscribers                 | Only recognised visitors whose email consent is subscribed. |
| Show to text messaging only subscribers        | Only recognised visitors whose SMS consent is subscribed.   |
| Show to specific profiles in a list or segment | Only visitors who are in at least one segment you pick.     |

This is resolved for the real visitor, not guessed in the browser. The storefront script sends the anonymous visitor id it already stores, and Senderz answers with only what the rules need: whether the visitor is known, whether they are subscribed on email and on SMS, which of the targeted segments they belong to, and their country. The answer never contains an email address, a phone number or a contact id, so a popup payload can never be read to enumerate your list.

<Warning>
  If you pick **Show to specific profiles in a list or segment** and select no segment, nobody sees the popup. An audience rule that cannot be satisfied hides the popup rather than falling back to everyone.
</Warning>

Only segments some live popup actually targets are looked up, so adding a segment rule to one popup costs nothing on the rest.

### URLs

Choose **Only show on certain URLs** or **Don't show on certain URLs**, then add one rule per line.

* `*` is a wildcard. `/products/*` matches every product page.
* `/` matches your whole site, not just the homepage. A new popup starts with `/`, which is why it shows everywhere until you narrow it.
* A rule without a wildcard matches the page exactly, or any page beneath it. `/products` matches `/products` and `/products/blue-shirt`.
* A rule containing `://` is matched against the full page address. A rule that starts with a path is matched against the path only.
* Trailing slashes, `#anchors` and tracking parameters are ignored, so `?utm_source=instagram` or `?fbclid=...` on an ad click does not stop a rule matching. If your rule carries its own query string, that query is kept and has to match.
* Non-Latin URLs match on the characters you see. A Hebrew permalink pasted from your admin matches the page even though the browser shows it percent-encoded.

<Note>
  Exclusions you added before switching to **Only show on certain URLs** stay saved and are still applied. In that mode a page has to match your include list **and** avoid any exclusion you had set earlier. Clear the exclusion list if you no longer want it.
</Note>

### Location

Country only. City targeting is not available. Enter ISO country codes such as `IL` or `US`, and choose whether the list is who to show to or who to hide from.

<Warning>
  **Location fails closed.** If Senderz cannot determine the visitor's country, a popup that carries any country rule does not show. This applies to both the include and the exclude option, so a "hide from US" rule also hides the popup from a visitor with no country signal. Leave the list empty if you would rather never suppress anyone.
</Warning>

### UTM parameters

Two independent settings sit under this heading and they do different things.

<CardGroup cols={2}>
  <Card title="Show based on UTM parameters" icon="filter">
    A targeting rule. Add entries like `utm_source=instagram`. Wildcards work,
    so `utm_campaign=spring-*` matches a family of campaigns.
  </Card>

  <Card title="Store UTM parameters" icon="floppy-disk">
    A capture setting. It saves the campaign the visitor arrived on to their
    profile when they subscribe.
  </Card>
</CardGroup>

**Every UTM rule must match.** They are combined with AND, not OR. A visitor who arrives without one of the parameters you listed does not see the popup.

**Storing UTM parameters** is off by default. Turn on **Store UTM parameters in the shopper's profile upon consent** and the `utm_source`, `utm_medium`, `utm_campaign`, `utm_term` and `utm_content` values from the page are written to the subscriber when they submit. They land as the contact properties `utmSource`, `utmMedium`, `utmCampaign`, `utmTerm` and `utmContent`, so you can filter on them in the [segment builder](/en/audience/segments) like any other property.

Three details worth knowing:

* Values are saved on subscribe, not on page view. A visitor who never submits leaves no trace.
* Blank parameters are skipped, so an empty value never overwrites a real one already on the profile.
* Senderz reads the setting off your stored popup, not off the request the browser sends, so the toggle is the only thing that decides whether anything is written.

### Cart contents

Three optional rules, usable together:

* **Show based on total cart value**, with a minimum.
* **Show based on number of items in cart**, with a minimum.
* **Show based on product type in cart**, with a list of types. The visitor's cart has to contain at least one of them.

<Warning>
  **Cart rules fail closed.** Reading the cart is opt-in, so if the cart cannot be read the popup does not show. Showing it to everyone instead would invert the rule you wrote. If a cart-targeted popup stops appearing on your store, the cart request is the first thing to check.
</Warning>

The cart is only fetched when at least one of your live popups targets it, so popups without cart rules cost your storefront nothing extra.

The **Cart contents** section only appears on platforms that expose a cart Senderz can read from the storefront: Shopify, WooCommerce and WordPress. Reading a cart on a WordPress site needs WooCommerce. [Konimbo](/en/integrations/konimbo) has no such endpoint, so the section is hidden there rather than offering a rule that could never match.

If you run a headless storefront, where the shop and the site sit on different domains, point Senderz at whatever path returns your cart JSON. Set it alongside the rest of your Senderz storefront configuration, before the popup script runs:

```js theme={"system"}
window.SenderzStorefront.cartEndpoint = "/api/cart";
```

## Display: when and how it shows

### Display priority

**High**, **Medium** or **Low**. When several popups qualify on the same page view, the higher priority one is armed first and wins a same-moment tie.

<Warning>
  Priority breaks a tie, it does not pre-empt. A **High** popup on a 30 second delay still loses to a **Low** one on a 2 second delay, because nothing can know the later timer will ever fire. If you need one popup to win outright, give it the earlier trigger, not the higher priority.
</Warning>

### Timing rules

Six trigger types are available:

| Rule               | What fires it                                                               | Value            | Default if left alone |
| ------------------ | --------------------------------------------------------------------------- | ---------------- | --------------------- |
| After a delay      | Time since the page loaded                                                  | 0 to 60 seconds  | 5 seconds             |
| On scroll depth    | How far down the page the visitor has scrolled                              | 1 to 100 percent | 50 percent            |
| On exit intent     | The pointer leaves the top of the window, or the tab is hidden              | none             | none                  |
| After time on page | Total time on the page                                                      | 5 to 600 seconds | 30 seconds            |
| After inactivity   | No mouse, key, scroll or touch activity. The clock restarts on any activity | 5 to 600 seconds | 30 seconds            |
| On click           | A click on an element matching your CSS selector                            | a CSS selector   | `[data-senderz-open]` |

**Rules are OR-ed.** Every rule you add is armed at the same time and the first one to happen shows the popup. The rest are torn down. Exit intent plus a 20 second delay plus a 60 percent scroll depth compose into "whichever happens first".

You can add up to **six** rules. **Add another rule** gives you the next trigger type you have not used yet, so in practice you build one rule per type.

<Note>
  A popup you have never edited here still shows a single row, built from the trigger it was originally saved with. That is what is genuinely armed. Editing it promotes that trigger into a real rule so your next edit is never lost.
</Note>

For **On click**, the selector defaults to `[data-senderz-open]`, so adding that attribute to any element on your storefront is enough:

```html theme={"system"}
<button data-senderz-open>Get 10% off</button>
```

If the element carries a value, only the popup with that id or that custom trigger handle opens:

```html theme={"system"}
<button data-senderz-open="welcome">Get 10% off</button>
```

A click rule ignores the frequency window, because the visitor asked for the popup. All the other rules on this page still apply. An invalid CSS selector is caught by the **Click trigger is valid** pre-launch check before you can publish.

### Frequency

**If the visitor closes the popup, show again after (days)**, between 0 and 365. A new popup starts at 7 days. `0` shows it on every visit.

<Warning>
  The window starts when the popup is **shown**, not when the visitor closes it. Senderz records the moment the popup appears, so a 7 day frequency means "at most once every 7 days in this browser" whether the visitor closed it after one second or read the whole thing. The field label talks about closing. The behaviour is measured from display.
</Warning>

The counter is per popup and per browser. Two different popups have two separate windows.

### After a submission

**Do not show again once submitted** is separate from the frequency above. Closing the popup hides it for a while. Submitting hides it for good in that browser.

Senderz records a successful submission whether or not this setting is on, so turning it on later immediately stops the popup for people who have already subscribed through it. There is no expiry on that record.

### Schedule

Pick the **active days** of the week and a **from** and **until** hour.

* Times follow the **visitor's own device clock**, not your workspace time zone.
* Setting the same start and end hour shows the popup all day. A new popup starts with every day and every hour selected.
* A window that wraps past midnight works. From `22:00` until `06:00` covers the night.

### Devices

Three choices: **All devices**, **Desktop only**, **Mobile only**.

<Note>
  **Tablets count as desktop.** "Desktop only" does not hide the popup from an iPad, because desktop here means "not a phone". If you genuinely need to exclude tablets, there is no setting for it.
</Note>

Devices and active days are both checked by the **Audience is reachable** pre-launch check. Clearing every device, or every day, blocks publishing rather than quietly publishing a popup nobody can see.

### Custom trigger

Open a popup from your own button, link or code:

```js theme={"system"}
window.SenderzStorefront.openForm("welcome");
```

Set a **Handle** in the Display tab to get a readable name, otherwise pass the popup id. Handles accept letters, numbers, hyphens and underscores, up to 40 characters. The builder shows the exact snippet with a copy button.

What the call does and does not skip:

<CardGroup cols={2}>
  <Card title="Skipped" icon="forward">
    The timing rules and the frequency window. You already decided this is
    the moment.
  </Card>

  <Card title="Still enforced" icon="shield">
    Audience, URLs, location, UTM, cart, devices, schedule, the publish
    window and "do not show again once submitted".
  </Card>
</CardGroup>

That split is deliberate. A handle is public, so it must not be able to widen a targeted popup to an audience you excluded.

The call returns `false` when no popup matches, when the popup does not qualify for this visitor, or when a popup is already open. Called before the popup list has loaded, it is replayed once for you as soon as the list arrives.

## Click outside form to close

Clicking the background around the popup dismisses it, the same as the close button. It is its own setting, per device, and both **On desktop** and **On mobile** are on unless you turn them off. A popup saved before this control existed keeps the behaviour it already had.

Two things hide or overrule the setting:

* **The display type has no backdrop.** Full screen, banner, sticky bar and floating popups paint no background, so there is nothing to click. The setting is hidden entirely on those four.
* **Close is hidden entirely.** That close behaviour exists to remove every way out, so it wins over both sides of this setting. The panel says so instead of offering a checkbox the popup would overrule. The Escape key is disabled in that mode too.

This is deliberately not a side effect of the close icon. Hiding the X but keeping a "No thanks" link still allows dismissal, and turning both sides off keeps the background inert even with the X still showing.

When a teaser is enabled with an after-close display mode, dismissing the popup leaves the teaser behind so the visitor can reopen it.

## What happens at the moment of display

Two rules decide the final outcome on a page.

**One popup shows per page view.** Once one popup opens, every other armed popup is torn down. On the next page view the count starts again, so a different popup can show. Across page views the frequency window is what limits a repeat.

**Every rule is re-checked at the moment of display, not only when it was armed.** A 60 second delay can outlive the hour window, cross a publish end date, or arrive after the visitor subscribed in another tab. If the popup no longer qualifies when its trigger fires, it does not open.

A teaser set to show before the form appears 2 seconds after load. It can only ever open the popup earlier, never suppress its own trigger.

## Publish window

Separate from the schedule above. In the publish panel, choose **Publish now** or **Schedule**, with a start and an optional end. The window is enforced when the popup list is served and re-checked at display, so a long delay that crosses the end time will not fire. The **Schedule is valid** pre-launch check blocks a start that is not before its end.

## Fails open or fails closed

Every rule has to decide what to do when its signal is missing. Getting this backwards either hides a popup that should show or shows one you targeted away.

| Rule                             | If the signal is missing                                                                                                       |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Audience                         | Fails closed. An unrecognised visitor is treated as not known, and an audience rule with no segments selected shows to nobody. |
| Location                         | Fails closed. No country means no popup, in both include and exclude mode.                                                     |
| UTM rules                        | Fails closed. A missing parameter fails the rule.                                                                              |
| Cart rules                       | Fails closed. An unreadable cart hides the popup.                                                                              |
| Frequency                        | Fails open. If the browser cannot read its own storage, the popup is treated as never shown.                                   |
| Do not show again once submitted | Fails open, for the same reason.                                                                                               |
| URLs, devices, schedule          | Always evaluable. The page address, the viewport and the device clock are always available.                                    |

Private browsing and blocked site storage therefore make frequency and once-submitted unreliable. Those visitors may see a popup again. Nothing is lost on the targeting side, because targeting does not depend on browser storage.

## Related

<CardGroup cols={2}>
  <Card title="Popups and forms" icon="window-restore" href="/en/messaging/popups">
    The builder, steps, blocks and on-site install.
  </Card>

  <Card title="Segments" icon="filter" href="/en/audience/segments">
    Build the segments an audience rule targets, and filter on captured UTM properties.
  </Card>

  <Card title="Consent" icon="check-double" href="/en/audience/consent">
    What a subscriber may actually be sent, which list membership does not decide.
  </Card>

  <Card title="Coupons" icon="ticket" href="/en/messaging/coupons">
    The rewards a popup can hand out.
  </Card>
</CardGroup>
