Popups — Reference
The Popups surface is the on-page promotional and conversion overlay system. It owns the popup record, the display rules that decide when a popup shows, the targeting rules that decide who sees it, the analytics ledger that records impressions and conversions, and the suppression layer that prevents repeat-firing after the visitor has already converted.
This page is a reference for platform engineers and integrators who need to understand the surface before extending it, scripting against it, or building reporting on its event stream. Customer-facing how-tos live in the customer docs set; this page describes the shape of the surface, not the steps to drive it.
Overview
Popups live under the Popups module in SG-Admin, inside the marketing sub-tree. The module renders three primary views — the popup list, the popup builder (where content + rules are authored together), and the analytics view — and exposes a small set of write operations for create, edit, duplicate, soft delete, and the publish toggle.
The popup builder is a composite surface — it pairs a content authoring pane (using the SGEN component system) with a rules pane (display triggers, targeting filters, frequency caps, suppression rules). Engineers reading the SG-Admin source will see this split — one half renders the components, the other half persists the rules — but the public-facing record is a single popup with both kinds of data attached.
The runtime side of Popups lives on the public site. When a page renders, the platform evaluates the active popup rule set against the current request context (URL, visitor segment, prior impression history, session state) and decides which popups (if any) become eligible for display. Eligible popups respect their own trigger condition before showing — time-on-page, scroll depth, exit intent, or explicit element click.
Where it lives in SG-Admin:
- Sidebar: SG-Admin → Marketing → Popups
- URL prefix:
/sg-admin/popups/ - View templates:
application/views/Admin/Popups/
┌──────────────────────────────────────────────────────────────────────┐│ SG-Admin → Marketing → Popups [+ New popup] │├──────────────────────────────────────────────────────────────────────┤│ Name Trigger Targeting State Conv % ││ ──────────────── ─────────────── ───────────── ──────── ────────││ Newsletter join Scroll 60% All pages Live 4.2% ││ Cart abandon Exit intent /cart/* Live 8.1% ││ Welcome (first) On load First visit Live 2.7% ││ Holiday promo Time 8s Homepage Paused — ││ Survey (post-buy) Element click /order/* Draft — ││ ││ [Edit] [Duplicate] [Pause] [Delete] │└──────────────────────────────────────────────────────────────────────┘Actions
The Popups surface exposes the following operations. Each is described by what it does to the data, not by its internal method name.
List and search
Returns the popup records visible to the current operator, paginated, with name, trigger, targeting summary, state, and 30-day conversion rate columns. Supports column sort, free-text filter, state filter, and per-page count. Driven by the data-table contract used across SG-Admin modules.
Create popup
Opens the popup builder in empty state. Required at minimum: name, content (at least one component), trigger type, and target rule (even if the target is "all pages"). Optional fields cover frequency cap, suppression duration, conversion event, and per-popup styling overrides. On submit, the surface validates the rule set for internal consistency (no contradictory targeting), persists the record, and returns the new identifier in draft state.
Edit popup
Loads an existing record into the builder, pre-populated. Content components and rules are both editable. Submit replaces the stored record with the posted values. Edits to a live popup take effect on the next page render — there is no separate publish step for edits.
Engineering note: edits to a live popup reset the impression ledger for the popup. This is intentional — a meaningful content or rule change invalidates prior impression data for A/B comparison. Operators who want to preserve the impression ledger use Duplicate.
Duplicate
Creates a copy of the popup with [copy] appended to the name and state forced to draft. The copy carries the same content + rules but starts a fresh impression ledger. Used for A/B testing variants or migrating a tested popup to a different campaign.
Toggle publish state
Moves the popup between draft, live, and paused. Only live popups participate in the page-render evaluation. draft and paused are equivalent for the runtime but distinguished in the operator UI — draft means never published; paused means previously live, now suspended.
Soft delete
Marks the record archived without removing it from the database. Soft-deleted popups disappear from the default list view, leave the runtime evaluation, and their impression ledgers are preserved for retroactive reporting.
Restore
Reverses a soft delete. The record returns to the active list in paused state — never auto-republished, to prevent surprise re-firing after archive.
Permanent delete
Hard-removes the record. Available only after a soft delete. Impression ledgers are detached and re-attributed to a system archive bucket. This path is irreversible.
View analytics
Loads the impression + conversion ledger for the popup, scoped to a date range. Renders three breakdowns: impressions over time, conversion rate over time, and a target-rule attribution chart showing which targeting condition produced the most conversions. Read-only — analytics here is rendered from event-stream data, not editable.
Suppression management
The suppression layer is exposed as a sub-action on the popup detail. Operators can view the current suppression cookie name + duration, view the cohort size of currently-suppressed visitors, and reset the suppression for a manually-entered visitor identifier (used for support cases where a visitor reports incorrect suppression behavior).
Data model
A popup record carries the following fields. Field names below are the conceptual shape — the on-disk column names match closely but are not contractually stable across releases.
| Field | Type | Notes |
|---|---|---|
id | integer | Primary key. Stable across edits. |
name | string | Operator-facing identifier. Not unique. |
content | object | Component tree rendered inside the popup shell. |
trigger | object | { type, params } — time / scroll / exit / element / on-load. |
targeting | object | Rule tree of URL patterns, segment filters, visitor conditions. |
frequency_cap | object | Max impressions per visitor per time window. |
suppression | object | Post-conversion suppression window — duration + scope. |
conversion_event | string | What counts as a conversion — form submit, click, custom event. |
state | enum | draft, live, paused, archived. |
priority | integer | Tie-breaker when multiple popups are eligible on the same render. |
impression_count | integer | Total impressions since last reset. |
conversion_count | integer | Total conversions since last reset. |
created_at | timestamp | Set on create, immutable. |
updated_at | timestamp | Touched on any edit. |
archived_at | timestamp | Set on soft delete. |
state = archived is the soft-deleted state. Soft-deleted popups retain all other fields and their event-stream history. Permanent delete detaches the event stream.Edit-reset semantics: content or rule edits to a live popup reset impression_count and conversion_count to zero. The underlying event stream is preserved, but the displayed counters reflect post-edit data.
Eligibility resolution: when multiple popups are eligible on the same page render, the highest priority value wins. Equal priorities are tie-broken by created_at (older first).
POPUP RECORD├── id integer primary key├── name string operator-facing├── content object component tree├── rules│ ├── trigger object time / scroll / exit / element / on-load│ ├── targeting object URL + segment + visitor conditions│ ├── frequency_cap object max impressions per visitor / window│ └── suppression object post-conversion suppression window├── conversion_event string what counts as a conversion├── state enum draft | live | paused | archived├── priority integer tie-breaker for multi-eligible renders├── counters impression_count, conversion_count (reset on edit)└── timestamps created_at, updated_at, archived_atPermissions
Access to the Popups surface is gated at two layers.
Layer 1 — admin gate. Every action under SG-Admin passes through the platform's standard admin access check at request entry. An unauthenticated request never reaches the Popups surface.
Layer 2 — per-action capability. Within SG-Admin, each Popups action checks a capability associated with the calling operator's role. The default role configuration uses the platform's base roles — Administrator, Editor, Viewer — augmented with a marketing-specific Marketer role. The capability map is:
| Capability | Administrator | Marketer | Editor | Viewer |
|---|---|---|---|---|
| List popups | ✔ | ✔ | ✔ | ✔ |
| View popup detail | ✔ | ✔ | ✔ | ✔ |
| Create popup | ✔ | ✔ | — | — |
| Edit popup | ✔ | ✔ | — | — |
| Duplicate | ✔ | ✔ | — | — |
| Toggle publish (draft ↔ live ↔ paused) | ✔ | ✔ | — | — |
| Soft delete | ✔ | ✔ | — | — |
| Restore | ✔ | ✔ | — | — |
| Permanent delete | ✔ | — | — | — |
| View analytics | ✔ | ✔ | ✔ | ✔ |
| Reset suppression for visitor | ✔ | ✔ | — | — |
Self-protection rules. A popup cannot be promoted to live while another popup with identical targeting + trigger + priority is already live (the platform rejects with a structured conflict response). Frequency caps below 1 are rejected. Suppression windows above 365 days are rejected.
Audit. Every write — create, edit, duplicate, state change, soft delete, restore, permanent delete, suppression reset — emits an Activity Log entry. The log records the acting operator, the target popup, and the change shape. Activity Log retention is governed by the site's general settings.
PAGE RENDER REQUEST│▼┌──────────────────────────────────┐│ Eligible popup set ││ — state == live ││ — targeting matches URL ││ — targeting matches segment ││ — visitor not in suppression ││ — frequency cap not hit │└────────────────┬─────────────────┘│▼Sort by priority (desc)│▼Take top N (config: usually 1)│▼Render with trigger attached(popup waits for trigger conditionbefore displaying)│▼On trigger → impression loggedOn conversion → suppression setper popup rulesRelated references
- Forms — Reference. Popups frequently host a form record — popup conversions are often form submissions, and the suppression layer reads the form's submission ledger to decide suppression.
- Tracking Consent — Reference. Popups that include analytics or marketing trackers respect the visitor's tracking consent state. Pre-consent popups do not write to the analytics stream.
- Pages — Reference. Popup targeting reads against page URL patterns. Page records here are referenced, not embedded.
- Custom Codes — Reference. Custom popup themes, custom suppression keys, and custom conversion events are configurable through the platform's template surfaces.
- Settings — Reference. Owns the per-site popup defaults — default frequency cap, default suppression duration, max concurrent popups per render.
- Email Campaigns — Reference. Popup conversions can enroll a visitor into a campaign — the campaign list is referenced from the popup's conversion_event configuration.
/docs/popups.