Popups

Create lightboxes, floating bars and inline messages with WordPress blocks.

Quick start

  1. Go to XPAC → Popups → All Popups.
  2. Click Add New Popup.
  3. Build the popup with normal WordPress blocks.
  4. Open Display Rules in the editor sidebar.
  5. Add a rule: choose Lightbox, add an Everywhere page condition, and select Time on Page → is immediate as the opening trigger.
  6. Save the rule, then publish the popup. Visit a matching page to check it.

A popup with no rule will not open by itself. You can still open it with a Popup Selector block.

TypeWhat it does
LightboxOpens over the page with a dimmed background.
Floating BarStays at the top or bottom of the window.
InlinePrints inside the page before the header or after the footer.

Display rules

Every rule answers three questions:

  1. Where? Choose the pages, posts, URLs or query strings.
  2. When? Choose a trigger.
  3. How? Choose the popup type, position, animation and close button.

You can add more than one rule to a popup. A rule must be enabled and inside its start/end dates.

Inline popups need a page condition but do not need a trigger. Combine conditions with any (OR) or all (AND). Keep the first rule simple and add targeting after confirming it opens. Dates use the WordPress site timezone; an end date includes that whole day. Leave either date blank for an open-ended schedule.

Frequency

For lightboxes and floating bars, under How often, set Dismiss for to a waiting period and choose whether to count opens or closes. Set both the delay and the count. For example, 7 days if popup closed 1 times waits seven days after the visitor closes it before showing it automatically again. Clear both numeric fields to remove the frequency limit.

Frequency is remembered in this browser using local storage. A visitor who clears site data, blocks storage or uses another browser can see the popup again.

Triggers

TriggerOpens when
Exit IntentThe pointer leaves through the top of the window.
Time on PageThe page opens or a timer ends.
Scroll DistanceThe visitor reaches a percentage or pixel depth.
HTML ElementA selector is clicked, hovered or receives a custom event.
InactivityThe visitor is idle for the chosen time.
Page ViewsThe visitor reaches the chosen page count in this session.

Exit intent requires a mouse or similar pointer and does not provide a touch gesture. Use another trigger for touch devices. Inactivity resets when the visitor interacts with the page. Page-view and visit limits use tab-session storage; they are not counts of unique people across devices. Page Views includes earlier pages in the same tab, including pages where the popup is not shown.

Closing

  • Close button, Close on Escape and Close on click outside (lightbox only) can each be switched off.
  • A lightbox keeps at least one of the three on. The last one left can't be switched off, unless a button in the content closes the popup.
  • A button or link with class xpac-popup-cta-close closes its popup.
  • Escape closes the active popup. With stacked popups, it dismisses one at a time. It closes an inline popup only while focus is inside it.

Use the Popup Selector block when a visitor should choose to open a popup.

  1. Add the block to a post or template.
  2. Select a published popup.
  3. Put a button, image or other blocks inside it.

The inner content becomes the opener. Use a Button or link for an opener that is naturally keyboard accessible. The block can open published content without automatic display rules. It bypasses automatic frequency and visit limits because the visitor requested it; Pause all popups and excluded paths still apply.

Opening the same popup as a lightbox and then as a floating bar switches its presentation and keeps any form entries. Different popups can remain open together; keyboard focus stays in the active lightbox.

Site settings

Go to XPAC → Popups → Settings. These settings apply to the whole site. Use the popup editor for an individual popup's design and display rules. Changes take effect after Save Changes; Discard restores the last saved values.

SettingMeaning
Pause all popupsStops popups without deleting rules.
Most popups on one pageMaximum automatic popups eligible on a page, from 1 to 20. 0 means unlimited.
Most popups in one visitMaximum distinct automatic popups per tab session, from 1 to 20. 0 means unlimited. Reopening the same popup does not consume another slot.
Count how popups performTurns anonymous counters on or off.
Never show popups on these pathsDisables popups on exact paths or path prefixes.

The per-page limit includes inline popups. Per-visit and repeat-appearance limits apply to lightboxes and floating bars; inline content is rendered with the page.

Path examples:

/checkout
/account/*

/checkout matches one path, with or without a trailing slash. /account/* matches /account and its descendants, but does not match /accounting. Only a trailing wildcard is supported. Matching ignores query strings. On a site installed at /blog, enter paths relative to that installation, such as /checkout for /blog/checkout.

Clear your full-page cache after changing settings, rules or schedules. Cached pages can contain the previous popup configuration until they are refreshed.

Statistics

The Overview shows four counts:

  • Could have opened — the popup was available on the page.
  • Opened — the popup appeared.
  • Closed — the visitor dismissed it.
  • Clicked — the visitor clicked an eligible link, button or submit control inside it; close controls are excluded.

Each count is recorded at most once per popup per page view. Editors are not counted. Popup-level totals and per-rule breakdowns are counted separately; adding the rule rows together does not give a popup's total.

Counts are sent when the page is hidden or left. Browser/network failures and content blockers can prevent delivery. These are engagement counts, not confirmed purchases or an audit log. The stats table stores daily aggregates by popup, rule and device bucket, without visitor identities. Turning counting off stops new counts without deleting existing totals.

Styling

A popup's content sits in a Popup box block. Select it to set the popup's width (Small, Medium, Large, Auto or a custom size) and its background, padding, border, radius and shadow. The editor shows the box as visitors see it.

  • A lightbox opens at the box's width, never wider than the screen.
  • A floating bar or inline popup stays full width. The box's background fills the bar and the content is centred at the box's width.
  • Auto keeps the popup's default width, the theme's content size.

Until you change the box, popups use the active theme's theme.json values for the surface, text, content size, spacing and shadow. Blocks inside the popup keep their normal WordPress styles.

The plugin only supplies the popup frame, placement, overlay and close button. It does not force a brand palette or font.

Add a class under Advanced → Additional CSS Class(es) in the popup editor sidebar when one popup needs a custom look:

.sale-popup {
  --xpac-pp-width: 38rem;
  --xpac-pp-container-padd: 3rem;
  --xpac-pp-shadow: var(--wp--preset--shadow--deep);
}

Useful variables:

VariableControls
--xpac-pp-widthLightbox width.
--xpac-pp-space-xSpace from the left and right edges.
--xpac-pp-space-ySpace from the top and bottom edges.
--xpac-pp-container-bgPopup surface color.
--xpac-pp-container-colorPopup text/close color.
--xpac-pp-container-paddInner padding.
--xpac-pp-overlay-bgLightbox overlay color.
--xpac-pp-shadowPopup shadow.

Use WordPress preset variables where possible. This keeps the popup correct when the site switches styles or color schemes.

Accessibility

  • Lightboxes use a modal dialog, move focus inside and trap Tab until closed.
  • Closing returns focus to the element that opened the popup.
  • Floating and inline popups use a named region and do not trap focus.
  • Background content becomes inert only while a lightbox is open.
  • Reduced-motion preferences replace movement with a short fade.

Import and export

Use Export as JSON from the popup list. Use Import to preview a file before creating anything.

Published popups become drafts on import; draft, pending and private statuses are preserved. Review their page IDs, URLs, content and enabled display rules on the destination site before publishing. JSON transfers content and configuration; it does not copy media files or statistics between sites.

Troubleshooting

The popup never opens

Check these in order:

  1. The popup is published.
  2. The rule is enabled.
  3. The rule has a page condition.
  4. A lightbox or floating bar has a trigger.
  5. The schedule includes today.
  6. Popups are not paused.
  7. The current path is not excluded.
  8. The automatic page/visit limit or the rule's frequency limit has not been reached. Try a fresh private tab to check this.
  9. The full-page cache has been cleared and the trigger matches the device.

In the Overview and popup list, review the rule status and any setup problems. For a popup opened only by a Popup Selector, test its actual opener.

The popup looks different from the editor

Put background, text and spacing styles on a Group or Cover block inside the popup. Check whether theme CSS targets only .wp-site-blocks; popup markup is added directly to the document body.

Inline content is missing

Try After Footer first. Before Header needs the theme to call wp_body_open().

For developers

See the Popups hook reference for every public action and filter.

PHP extensions

Register add-on schema and configuration filters during xpac_popups_init. For example, to disable the built-in counts for requests where your own consent check has not granted permission:

add_filter('xpac_popups_count_visitor', function ($count, $enabled) {
    return $enabled && $count && my_site_allows_popup_analytics();
}, 10, 2);

my_site_allows_popup_analytics() is your site's consent check. Keep the $enabled and $count checks to honor the global switch and editor exclusion. Sites with full-page caching must make sure personalized consent decisions are not shared between visitors. Use xpac_popups_settings_updated to connect global changes to your cache purge.

Browser lifecycle events

The runtime dispatches these DOM events on document and on the popup template:

EventTiming
xpac-popup-pre-openBefore opening the popup.
xpac-popup-post-openAfter the popup is visible and focus is set.
xpac-popup-pre-closeBefore removing the open popup.
xpac-popup-post-closeAfter removal and focus restoration.

On document, event.detail contains template and the active rule. The post-open event also includes requested: true for an explicit block opener. Events are notifications, are not cancelable, and are dispatched separately on the template and document rather than bubbling. Listen on one target to avoid handling the same transition twice.

document.addEventListener('xpac-popup-post-open', (event) => {
  const { template, rule, requested } = event.detail;
  const { id } = template.xpacPopup.getSettings();
  // Connect id, rule.id and requested to your integration here.
});

These events describe runtime lightboxes and floating bars. Server-rendered inline regions have no template interface and do not emit this lifecycle. JavaScript filters such as xpac-popups-triggers use @wordpress/hooks and must be registered before the popup runtime initializes. Consult the generated reference for each filter's parameters and return contract.

On this page