* [/gosmartmodal]
*
* 2) That’s it. The first popup appears on exit intent. The second appears after 3 seconds
* of inactivity. Clicking “View Plans” closes the popup and scrolls to the #pricing section.
*
* What each part means
* - Shortcode wrapper: [gosmartmodal width="700" id="welcome-offer"] ... [/gosmartmodal]
* • width: limits the popup’s max width.
* - Number only → treated as pixels (e.g., 700 → 700px)
* - CSS length value → e.g., 70vw, 90%, 40rem, 32em, 720px
* - Default: 700 (px)
* - Note: complex CSS functions like calc() are not supported here.
* • id: unique identifier used to scope dismissal memory per popup instance.
* - Allowed characters: letters, numbers, underscore, hyphen
* - Default: auto‑generated unique id
* - Reusing the same id across pages shares the dismissal memory.
*
* - Inner blocks: each
inside controls one popup instance with its own settings.
* • open_on (required): when to open this popup.
* - "exit" or "exit-intent" → show on exit intent (desktop only)
* - "idle:N" → show after N seconds of no mouse/keyboard/scroll activity
* • N can be a whole number or decimal (e.g., idle:3, idle:2.5)
* - "scroll:X%" → show after visitor has scrolled X percent down the page
* - "scroll:Ypx" → show after visitor has scrolled Y pixels down the page
* • position: where the popup sits on screen.
* - "top", "center" (default), or "bottom"
* • dismiss: auto‑close timer for this popup.
* - Seconds: "10s", "2.5s"
* - Milliseconds with unit: "5000ms"
* - Bare milliseconds: "10000"
* - Omit or set to 0/empty to disable auto‑close
* • dismiss_for: how long this popup stays dismissed after it opens (exit/idle).
* - Seconds: "10s", "2.5s"
* - Minutes: "30m", "0.5m"
* - Hours: "1h", "1.5h"
* - Milliseconds with unit: "5000ms"
* - Bare milliseconds: "1800000"
* - Use 0 to disable dismissal memory for this instance
* - Default: "30m"
*
* Full attribute reference (quick lookup)
* - [gosmartmodal] wrapper attributes
* • width (string|number): max content width. Accepts integer (px) or a CSS length keyword like 70vw, 90%, 40rem, 32em, 720px. Default: 700.
* • id (string): unique slug used to scope dismissal memory per popup. Allowed: A–Z, a–z, 0–9, _, -. Default: generated.
* - Inner
attributes (one overlay per
)
* • open_on (string, required): "exit", "exit-intent", "idle:N" (N seconds, decimals allowed), or
* "scroll:X%|Ypx" (X percent of page, or Y pixels from top).
* • position (string): "top" | "center" | "bottom". Default: "center".
* • dismiss (string|number): "Xs" (seconds), "Yms" (milliseconds), or bare number in ms. Default: no auto‑close.
* • dismiss_for (string|number): memory window after opening via exit/idle. Formats: "Xs", "Xm", "Xh", "Yms", or bare ms. 0 disables. Default: 30m.
*
* Examples
* - Exit intent with bottom position and no auto‑close:
*
* ...
*
* - Idle after 2.5 seconds, auto‑close after 6 seconds, at the top:
*
...
* - Idle after 8 seconds with dismiss set via milliseconds:
*
...
* - Show after scrolling 60% of the page:
*
...
* - Show after scrolling 800 pixels:
*
...
*
* Behavior notes
* - Dismissal memory: When a popup opens via exit/idle, it won’t open again for the per‑popup
* dismiss_for duration (default 30 minutes) for the same [gosmartmodal id] + reason ("exit",
* "idle:N", or "scroll:THRESHOLD"). Use a different id to treat it as a separate campaign.
* - Accessibility: role="dialog", aria-modal="true", ESC key closes. Focus moves to the
* close button on open. Clicking backdrop closes.
* - Links with class .gosmartmodalbutton close the popup first, then navigate. #hash links
* smooth‑scroll after closing.
*
* Styling and classes you can reuse
* - .gosmartmodalcoupon → just a bold helper for coupon codes
* - .gosmartmodalbutton → any link with this class will close the popup before navigating
* - The popup layout uses a small set of prefixed classes (gosmartmodal‑*) so it won’t
* clash with your theme. You can add your own CSS as needed.
*
* Accessibility and behavior
* - Popups include role="dialog", aria-modal="true", and can be closed with the ESC key.
* - Focus moves to the close button when a popup opens.
* - Clicking outside the popup (on the dimmed background) also closes it.
*
* Helpful tips
* - Not seeing the exit popup? Try moving the mouse up toward the top of the browser window
* (where tabs/address bar live). Exit intent doesn’t run on phones.
* - If you closed a popup and want to see it again while testing, wait 30 minutes or
* clear local site data for the page (the dismissal memory lives in your browser storage).
* - Links to on‑page anchors like #pricing will smooth‑scroll after the popup closes.
* - If you closed a popup and want to see it again while testing, either set dismiss_for="0"
* on that popup or wait for its dismiss_for period to elapse (30 minutes by default).
* - If you place a Gravity Form inside and it looks “frozen” until the popup opens,
* that’s expected—scripts wait until the form is visible. Once the popup opens,
* the form behaves normally.
*
* What this does not do
* - It won’t block the browser’s Back/Close buttons or show a custom popup at the exact
* moment a tab is closing—that’s a browser safety rule. Use the idle trigger for mobile.
*
* Need to customize?
* - We can tweak timings, positions, or add small design changes without changing your content.
* - You’re free to include any HTML in the popup content area, including images, headings,
* and Gravity Forms shortcodes.
*/
// Security: don't load directly.
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! function_exists( 'bl_register_gosmartmodal_shortcode' ) ) {
/**
* Register the [gosmartmodal] shortcode.
*/
function bl_register_gosmartmodal_shortcode() {
add_shortcode( 'gosmartmodal', 'bl_gosmartmodal_shortcode' );
}
add_action( 'init', 'bl_register_gosmartmodal_shortcode' );
}
if ( ! function_exists( 'bl_gosmartmodal_shortcode' ) ) {
/**
* Render the [gosmartmodal] shortcode.
*
* @param array $atts Shortcode attributes (width, id).
* @param string|null $content Shortcode inner content containing