Hyphen User Guides

Conversion Surfaces

Feature description and testing guide for conversion surfaces — modals, banners, slide-ins, and inline prompts

Version 1.0|Updated 2026-04-12|QA Team, Customer Success, Product Stakeholders

1. What Are Conversion Surfaces?

Conversion Surfaces are promotional overlays that appear on the Reader Portal to encourage readers to take a desired action — like registering for a free account, subscribing to a paid plan, signing up for the newsletter, or visiting a campaign page.

Think of them as smart, configurable pop-ups that know:

  • Who to show to (anonymous visitors, registered readers, subscribers)
  • Where to show (which pages, which device types)
  • When to show (after scrolling, after time on page, on exit intent)
  • How often to show (once per session, once per day, once per week)
  • What to say (custom title, description, image, call-to-action buttons)
  • What to offer (linked coupon code, specific subscription plan)

They are NOT random pop-ups. Each surface is a deliberately crafted, targeted touchpoint in the reader's journey, designed to convert at the right moment without disrupting the reading experience.


2. Business Objectives

ObjectiveHow Conversion Surfaces Help
Grow registered reader baseShow registration prompts to anonymous visitors after they've engaged with content
Convert free readers to paid subscribersPresent subscription offers at high-intent moments (after finishing an article, on paywalled content)
Grow newsletter audienceOffer newsletter sign-up at contextually relevant points
Promote campaigns & eventsDrive awareness for literary events, writing contests, and outreach campaigns
Drive e-commerce salesPromote bookstore products to engaged readers
Recover abandoning visitorsCapture attention on exit intent before readers leave the site
Distribute discount codesDeliver coupon codes through targeted, timed promotional surfaces
Measure marketing effectivenessTrack impressions, clicks, conversions, and attribution through GA4 and internal analytics

3. Key Concepts & Terminology

TermMeaning
SurfaceA single promotional overlay instance with its own content, targeting, and trigger rules
Surface TypeThe visual format (modal, banner, slide-in, sticky notification, inline embed)
Conversion GoalThe desired reader action (register, subscribe, view campaign, etc.)
Targeting RulesConditions that determine who is eligible to see the surface
TriggerThe event that causes the surface to actually appear (scroll depth, time on page, etc.)
Frequency CapHow often the same reader sees the same surface
SuppressionRules that prevent a surface from appearing (after dismissal, after conversion)
PriorityWhen multiple surfaces are eligible, the highest priority one is shown
ImpressionThe surface was displayed to a reader
ClickThe reader clicked the primary CTA
DismissThe reader closed/dismissed the surface
ConversionThe reader completed the desired action
EligibleThe surface passed all targeting checks and is ready to be triggered

4. Surface Types — What Readers See

Conversion surfaces list
View and manage all conversion surfaces — modals, banners, slide-ins, and inline prompts — with targeting and scheduling.

4.1 Modal

A centered overlay that appears on top of the page content with a semi-transparent backdrop.

PropertyValue
VisualCentered card with backdrop blur
PlacementAlways center of viewport
SizeMedium card (max-width ~480px on desktop)
Mobile behaviorSlides up from bottom as a bottom sheet
DismissalClick backdrop, click X button, press Escape
ContentTitle, subtitle, body text, image, primary CTA, secondary CTA, optional coupon code
Best forHigh-priority prompts (subscription, registration), exit intent captures

When to use: When you want to demand attention. The reader must interact with it (click CTA or dismiss) before continuing.


4.2 Sticky Notification

A small, persistent card that appears at a corner of the screen.

PropertyValue
VisualCompact floating card with shadow
PlacementBottom-right (default), bottom-left, top-right, top-left
SizeSmall — does not block content reading
Mobile behaviorCompact card at bottom of screen
DismissalClick X button
ContentTitle, short body text, primary CTA, optional coupon
Best forLow-disruption prompts, newsletter sign-up nudges

When to use: When you want to be present but not intrusive. The reader can continue reading while seeing the notification.


4.3 Slide-In Panel

A full-height panel that slides in from the right side of the screen.

PropertyValue
VisualFull-height panel with backdrop
PlacementSlides from right edge
Size~400px wide panel
Mobile behaviorFull-width panel from bottom
DismissalClick backdrop, click X button, press Escape
ContentFull rich content area — title, subtitle, body, image, CTAs, coupon
Best forDetailed offers, plan comparisons, event promotions

When to use: When you need more space to present an offer or detailed information without navigating away from the current page.


4.4 Top Banner

A full-width strip at the top of the page.

PropertyValue
VisualFull-width horizontal strip fixed to top of viewport
PlacementAbove all content
SizeThin horizontal bar (~60-80px height)
Mobile behaviorSame — full-width top bar
DismissalClick X button
ContentTitle (compact), primary CTA button
Best forSite-wide announcements, time-limited offers, simple CTAs

When to use: When you want maximum visibility with minimum disruption. Good for announcements that every reader should notice.


4.5 Bottom Banner

Same as top banner but fixed to the bottom of the viewport.

PropertyValue
VisualFull-width horizontal strip fixed to bottom of viewport
PlacementBelow all content
Best forPersistent subtle CTAs, cookie-banner-style promotions

When to use: When you want presence without competing with the header navigation area.


4.6 Inline Embed

An embedded card that appears within the page content flow (between sections or after article content).

PropertyValue
VisualSelf-contained card rendered inline within the page
PlacementWithin page content (position configured by the system)
SizeFull content width
Mobile behaviorFull-width card in content flow
DismissalCannot be dismissed — it's part of the content
ContentTitle, body text, CTA, optional coupon
Best forContextual promotions that feel like part of the editorial experience

When to use: When you want the promotion to feel native to the page, not like an interruption.


5. Conversion Goals — What You Want Readers to Do

Each surface must be assigned one conversion goal. This determines what action counts as a "conversion."

GoalDescriptionTypical CTATarget Audience
registerGet the reader to create a free account"Create Free Account" / "Sign Up"Anonymous visitors
loginGet a registered reader to sign back in"Sign In"Returning anonymous visitors
subscribe_paidGet the reader to purchase a subscription"Subscribe Now" / "View Plans"Anonymous + registered (non-subscribers)
subscribe_newsletterGet the reader to join the email newsletter"Subscribe to Newsletter"Readers not yet on the mailing list
view_campaignDrive traffic to a marketing campaign page"Learn More" / "Join the Event"All or targeted audiences
view_eventDrive attendance to a literary event"RSVP Now" / "View Event Details"All audiences
redeem_couponGet readers to use a promotional discount code"Get 20% Off" / "Claim Offer"Targeted audiences
view_productDrive traffic to a product in the bookstore"Shop Now" / "View Book"All audiences
visit_pricingDrive readers to the subscription pricing page"See Pricing" / "Compare Plans"Non-subscribers
custom_ctaAny other action with a custom URLCustom labelAny audience

6. Targeting Rules — Who Sees a Surface

Targeting rules are the first layer of filtering. A reader must match ALL the targeting criteria to be considered eligible.

6.1 Audience Targeting

AudienceWho It Includes
anonymousVisitors who are not logged in
registeredReaders who have a free account but no active subscription
subscriberReaders with an active paid subscription
newsletter_subscribedReaders who are on the email newsletter list
newsletter_unsubscribedReaders who have not subscribed to the newsletter

Rule: If the surface targets ["anonymous", "registered"], it will show to both anonymous visitors AND logged-in free readers, but NOT to paid subscribers.

Important: If the audience list is empty [], the surface matches ALL audiences (no audience restriction).

6.2 Page Type Targeting

Restrict which types of pages the surface appears on:

Page TypeDescription
homepageThe main landing page
articleIndividual article reading pages
sectionSection listing pages (Fiction, Poetry, etc.)
archiveArchive and issue browsing pages
searchThe search results page
tagTag listing pages
authorAuthor profile pages
subscribeSubscription/pricing pages
shopBookstore pages
campaignCampaign landing pages
issueMagazine issue detail pages
newsletterNewsletter archive pages

Rule: If the page type list is empty, the surface matches ALL page types.

6.3 Device Type Targeting

DeviceDescription
desktopScreen width > 1024px
tabletScreen width 768px - 1024px
mobileScreen width < 768px

Rule: If the device list is empty, the surface matches ALL devices.

6.4 Content Targeting (Advanced)

For article pages, surfaces can target based on content attributes:

RuleDescriptionExample
contentTypesArticle content types["fiction", "poetry"]
sectionsArticle section slugs["fiction", "essays"]
tagsArticle tag slugs["south-asian-lit", "translation"]

6.5 URL Targeting (Advanced)

RuleDescriptionExample
excludeUrlsPages where the surface should never appear["/account/*", "/subscribe/checkout"]
includeUrlsOnly show on these specific pages["/fiction/*", "/poetry/*"]

6.6 UTM Targeting (Advanced)

RuleDescriptionExample
utmSourceOnly show to visitors from specific sources["facebook", "twitter"]
utmMediumOnly show to visitors from specific mediums["social", "email"]
utmCampaignOnly show to visitors from specific campaigns["spring-promo"]

7. Trigger Rules — When a Surface Appears

After a reader is deemed eligible (passes all targeting rules), the trigger determines the exact moment the surface appears.

TriggerHow It WorksConfigurationBest For
page_loadShows immediately when the page loadsNo configuration neededUrgent announcements, time-sensitive offers
time_on_pageShows after the reader has been on the page for N secondstriggerDelaySeconds: 30 (e.g., show after 30 seconds)Engaged readers who are spending time reading
scroll_depthShows when the reader scrolls past a certain percentage of the pagetriggerScrollPercent: 50 (e.g., show at 50% scroll)Readers who are actively reading through content
exit_intentShows when the reader moves their mouse toward the browser's close/back button (desktop only)No configuration neededLast-chance conversion before the reader leaves
page_view_countShows when the reader has viewed N pages in the current sessiontriggerPageViews: 3 (e.g., show after 3 pages)Engaged visitors who are browsing multiple pages
after_article_readShows after the reader has finished reading an article (scrolled to ~90% + spent sufficient time)No configuration neededHigh-intent moment after content consumption

Important: Exit intent only works on desktop. On mobile, the system falls back to scroll_depth (75%) as an equivalent signal.


8. Frequency & Suppression — How Often a Surface Appears

8.1 Frequency Capping

Each surface has a frequency limit that controls how many times a reader sees it within a time window.

SettingDescriptionExample
frequencyLimitMaximum number of times to show1 = show once
frequencyUnitTime window for the limitsession, day, week, or month

Examples:

  • frequencyLimit: 1, frequencyUnit: day = Show at most once per day
  • frequencyLimit: 3, frequencyUnit: week = Show up to 3 times per week
  • frequencyLimit: 1, frequencyUnit: session = Show once per browser session

8.2 Dismissal Suppression

When a reader dismisses (closes) a surface, you can configure how long before they see it again:

SettingDescription
suppressAfterDismiss: 0Only suppress for the current session
suppressAfterDismiss: 1Suppress for 1 day after dismissal
suppressAfterDismiss: 7Suppress for 7 days after dismissal
suppressAfterDismiss: 30Suppress for 30 days after dismissal

8.3 Conversion Suppression

SettingDescription
suppressAfterConversion: trueIf the reader clicks the CTA and completes the action, never show this surface again
suppressIfConverted: trueIf the reader has already achieved the goal through ANY means (e.g., already registered), never show this surface

Example: A "Register" surface with suppressIfConverted: true will never show to a reader who is already logged in, even if they've never seen this specific surface before.

8.4 How Frequency State Is Tracked

  • Anonymous readers: Frequency state is tracked in the browser's localStorage. Clearing browser data resets the frequency state.
  • Authenticated readers: Frequency state is tracked both in localStorage (for speed) and in the ConversionEvent table on the server (for cross-device accuracy). Server-side checks are performed for authenticated readers during the eligible API call.

9. Scheduling & Lifecycle — When a Surface Is Active

9.1 Status Lifecycle

Every surface goes through a lifecycle of statuses:

                                    (cron: startsAt reached)
    draft -------> scheduled --------------------------> active
      |                |                                   |
      |                |                                   | (manual)
      v                v                                   v
   archived         archived                             paused
                                                           |
                      (cron: endsAt passed)                | (manual)
                    active ---------> expired               v
                                        |                active
                                        v
                                     archived
StatusMeaningVisible to Readers?
draftBeing created/edited, not visibleNo
scheduledHas a future startsAt date, will auto-activateNo
activeCurrently live and showing to eligible readersYes
pausedTemporarily disabled by adminNo
expiredPast its endsAt date, auto-deactivatedNo
archivedPermanently retired, preserved for analyticsNo

9.2 Allowed Status Transitions

FromCan Transition To
draftactive, scheduled, archived
scheduledactive, draft, archived
activepaused, archived
pausedactive, archived
expiredarchived
archived(terminal state — no transitions)

9.3 Automatic Transitions (Cron Job)

A background cron job runs every 15 minutes and:

  1. Activates surfaces where status = scheduled AND startsAt <= now
  2. Expires surfaces where status = active AND endsAt < now

This means:

  • A scheduled surface will go live within ~15 minutes of its start time
  • An active surface will expire within ~15 minutes of its end time

9.4 Immediate Activation

If you don't set a startsAt date and change the status directly from draft to active, the surface starts showing to readers immediately.


10. Priority & Conflict Resolution — Which Surface Wins

When multiple surfaces are eligible for the same reader on the same page, only one is shown. The system resolves conflicts using priority ordering:

  1. Surfaces are ranked by priority (higher number = higher priority)
  2. If two surfaces have the same priority, the more recently created one wins
  3. Only one overlay surface (modal, slide-in, banner, sticky) is shown per page load
  4. Inline embed surfaces are an exception — they render within the content and do not compete with overlay surfaces

Example: If both a modal (priority 15) and a sticky notification (priority 10) are eligible, only the modal appears.

Best practice: Set subscription-focused surfaces at priority 15-20, registration surfaces at 10-15, and informational surfaces at 1-10.


11. Coupon Integration — Promo Codes on Surfaces

Surfaces can be linked to a discount coupon from the platform's coupon system.

What Happens When a Coupon Is Linked

  1. Display: The surface shows the coupon code prominently with a "Copy Code" button
  2. Copy tracking: When the reader clicks "Copy Code," a coupon_copied event is recorded in both the internal analytics and GA4
  3. Auto-apply at checkout: If the surface CTA links to a checkout or subscribe page, the coupon code is automatically appended to the URL as ?coupon=CODE. The checkout page reads this parameter and auto-fills the promo code input field, applying the discount without the reader needing to type anything.
  4. Validation: The eligible API checks that the coupon is:
    • Currently active (isActive = true)
    • Not expired (validTo >= now or validTo is null)
    • Not exhausted (usedCount < maxUses)
    • If any check fails, the coupon is NOT shown to the reader

Example Flow

  1. Admin creates a surface with a coupon "SPRING20" (20% off) linked to the Premium Annual plan
  2. Reader visits an article, scrolls to 50%, and the modal appears: "Subscribe and save 20%! Use code SPRING20"
  3. Reader clicks "Copy Code" — code is copied to clipboard, coupon_copied GA4 event fires
  4. Reader clicks "Subscribe Now" — redirected to /subscribe/checkout?plan=premium-annual&coupon=SPRING20
  5. Checkout page auto-fills the promo code field with "SPRING20" and shows the discounted price

12. Entity Linking — Connecting Surfaces to Platform Entities

Surfaces can be linked to existing platform entities to provide context and ensure data consistency:

EntityFieldPurposeExample
Subscription PlanplanIdLinks to a specific subscription plan; plan details shown on surfacePremium Annual plan
Discount CouponcouponIdLinks to a promo code; shown on surface with copy button"SPRING20" coupon
CampaigncampaignIdLinks to a marketing campaign; CTA links to campaign pageLiterary Festival campaign
EventeventIdLinks to an event; CTA links to event RSVPAuthor Reading event
ProductproductIdLinks to a shop product; CTA links to product pageNew novel in bookstore
NewsletternewsletterSlugLinks to a newsletter editionWeekly fiction digest

Important: When linked entities become inactive (e.g., a plan is deactivated, a coupon expires), the eligible API automatically excludes them from reader-facing responses.


13. Analytics & Tracking — Measuring Surface Performance

Conversion surfaces management
The conversion surfaces list shows all configured surfaces with their type, status, targeting rules, and performance metrics. Click any surface to view its analytics.

13.1 Internal Analytics (ConversionEvent Table)

Every interaction is recorded as a ConversionEvent with:

  • Event type: impression, click, dismiss, conversion, coupon_copied
  • Reader context: readerId (if authenticated), sessionId
  • Page context: pageUrl, pageType, deviceType
  • UTM context: utmSource, utmMedium, utmCampaign
  • Metadata: trigger type, scroll percentage, and other event-specific data

13.2 Denormalized Counters

For quick access, each surface maintains running totals:

  • impressionCount — total times the surface was displayed
  • clickCount — total CTA clicks
  • dismissCount — total times the surface was dismissed
  • conversionCount — total successful conversions

These counters are updated atomically when events are recorded.

13.3 GA4 Events

The system fires the following Google Analytics 4 events:

GA4 EventWhen FiredParameters
conversion_surface_impressionSurface is displayed to a readersurface_id, surface_type, conversion_goal, trigger_type, page_type
conversion_surface_clickReader clicks the primary CTAsurface_id, surface_type, conversion_goal, cta_url
conversion_surface_dismissReader closes/dismisses the surfacesurface_id, surface_type, conversion_goal
conversion_surface_conversionReader completes the desired actionsurface_id, surface_type, conversion_goal
coupon_copiedReader copies the coupon codesurface_id, coupon_code

13.4 Admin Stats Dashboard

The admin can view detailed analytics for each surface:

  • Totals: Impressions, clicks, dismissals, conversions, coupons copied
  • Rates: CTR (click-through rate), dismiss rate, conversion rate, engagement rate
  • Time series: Daily/weekly/monthly breakdown of all metrics
  • Breakdown by device: Desktop, mobile, tablet splits
  • Breakdown by page type: Which pages drive the most conversions
  • Breakdown by UTM source: Which traffic sources convert best

14. UTM Attribution — Tracking Marketing Source

All conversion surface CTA URLs are automatically enriched with UTM parameters:

ParameterValuePurpose
utm_sourceconversion_surfaceIdentifies the traffic source as a conversion surface
utm_mediumpromoIdentifies the medium as promotional
utm_campaigncs_{goal}_{surfaceId}Identifies the specific surface and its goal

Rules:

  • UTM params are only added to internal URLs (relative paths or same-origin URLs)
  • If the URL already has UTM parameters, they are NOT overwritten
  • This allows GA4 to attribute downstream conversions (subscriptions, registrations) back to the specific surface that drove them

15. Reader Portal Rendering — How It All Works Together

15.1 Architecture

RootLayout
  |
  +-- GlobalConversionSurfaces
        |
        +-- ConversionSurfaceProvider (fetches eligible surfaces)
              |
              +-- ConversionSurfaceRenderer (evaluates triggers, renders surfaces)
                    |
                    +-- ModalSurface
                    +-- StickyNotificationSurface
                    +-- SlideInSurface
                    +-- BannerSurface (top or bottom)
                    +-- InlineEmbedSurface

15.2 Rendering Flow

  1. Page navigation detected: GlobalConversionSurfaces detects the current page type from the URL
  2. Eligibility fetch: ConversionSurfaceProvider calls the eligible API with page context (page type, URL, device type, session ID)
  3. Server-side filtering: The API evaluates all active surfaces against targeting rules and returns eligible ones, sorted by priority
  4. Client-side trigger evaluation: ConversionSurfaceRenderer listens for the configured trigger event (scroll, time, exit intent, etc.)
  5. Frequency check: Before displaying, the renderer checks localStorage for frequency caps and suppression state
  6. Surface display: The highest-priority eligible surface is rendered using the appropriate surface component
  7. Event tracking: Impression event is recorded (both internal API and GA4)
  8. Reader interaction: Click, dismiss, or conversion events are tracked as the reader interacts

15.3 Page Suppression

Conversion surfaces are automatically suppressed (never shown) on:

Page TypeReason
Auth pages (/login, /register)Reader is already in an auth flow
Account pages (/account/*)Reader is already logged in and managing their account
Subscribe pages (/subscribe/*)Reader is already in the subscription flow
Maintenance pageSite is in maintenance mode
Preview modeAdmin is previewing content

16. Admin Console — Managing Surfaces

16.1 Navigation

Admin Console > Marketing > Conversion Surfaces

16.2 List Page

Shows all conversion surfaces with:

  • Name, type (icon), goal, status badge
  • Priority, impression/click/conversion counts
  • Date range (starts at - ends at)
  • Filter by: status, surface type, conversion goal
  • Sort by: name, status, priority, impressions, clicks, conversions, created date
  • Search by name
  • Actions: Edit, Duplicate, Archive

16.3 Create/Edit Form

The form is organized into 7 sections:

Section 1: Basic Information

  • Name (internal label, not shown to readers)
  • Surface Type (modal, banner, etc.)
  • Conversion Goal
  • Priority (1-100, higher = shown first)

Section 2: Content

  • Title (required, shown to reader)
  • Subtitle (optional)
  • Body Text (optional, rich text)
  • Image URL (optional)
  • Background Color (optional)
  • Theme (light, dark, brand)

Section 3: Call-to-Action

  • Primary CTA Label (required, e.g., "Subscribe Now")
  • Primary CTA URL (required, e.g., "/subscribe")
  • Secondary CTA Label (optional, e.g., "Maybe Later")
  • Secondary CTA URL (optional, or auto-dismiss action)

Section 4: Entity Links

  • Linked Coupon (dropdown of active coupons)
  • Linked Subscription Plan (dropdown of active plans)
  • Linked Campaign, Event, Product, Newsletter (optional)

Section 5: Targeting

  • Audience segments (multi-select)
  • Page types (multi-select)
  • Device types (multi-select)
  • Content types, sections, tags (advanced)
  • URL include/exclude patterns (advanced)
  • UTM source/medium/campaign filters (advanced)

Section 6: Trigger

  • Trigger type (dropdown)
  • Trigger configuration (delay seconds, scroll %, page view count)

Section 7: Frequency & Scheduling

  • Frequency limit + unit
  • Suppress after dismiss (days)
  • Suppress after conversion (boolean)
  • Suppress if already converted (boolean)
  • Start date (optional, for scheduling)
  • End date (optional, for auto-expiration)

16.4 Permissions (RBAC)

PermissionActions
MARKETING_CONVERSION_SURFACES_READView list, view details, view stats
MARKETING_CONVERSION_SURFACES_CREATECreate new surfaces, seed templates
MARKETING_CONVERSION_SURFACES_UPDATEEdit surfaces, change status
MARKETING_CONVERSION_SURFACES_DELETEArchive surfaces

17. Pre-Built Templates — Getting Started Quickly

The system includes 15 pre-built template surfaces covering all conversion goals. These are seeded via the /api/marketing/conversion-surfaces/seed endpoint and created in draft status so admins can customize them before activating.

#Template NameTypeGoalTrigger
1Registration -- Exit Intent ModalModalregisterexit_intent
2Registration -- After 3 Page Views BannerTop Bannerregisterpage_view_count (3)
3Subscribe -- After Article Read ModalModalsubscribe_paidafter_article_read
4Subscribe -- Pricing Page StickyStickyvisit_pricingtime_on_page (10s)
5Subscribe -- 50% Scroll Slide-InSlide-Insubscribe_paidscroll_depth (50%)
6Newsletter -- Bottom BannerBottom Bannersubscribe_newsletterpage_load
7Newsletter -- Article Inline EmbedInline Embedsubscribe_newsletter(inline)
8Campaign -- Event Promo ModalModalview_campaigntime_on_page (15s)
9Campaign -- Sticky NotificationStickyview_eventpage_load
10Coupon -- Limited Time Offer ModalModalredeem_coupontime_on_page (20s)
11Coupon -- Flash Sale BannerTop Bannerredeem_couponpage_load
12Product -- Book Promo StickyStickyview_productscroll_depth (30%)
13Pricing -- Comparison PromptModalvisit_pricingafter_article_read
14Login -- Returning Visitor PromptStickyloginpage_view_count (2)
15Custom CTA -- Generic PromoSlide-Incustom_ctascroll_depth (40%)

18. Page Suppression — Where Surfaces Never Appear

Suppressed PagesReason
/login, /registerReader is already in auth flow — showing a "register" surface here would be redundant and confusing
/account/*Reader is logged in and managing their account — surfaces would be intrusive
/subscribe/*Reader is already in the subscription flow — competing CTAs would disrupt checkout
/maintenanceSite is under maintenance

19. User Stories

For Marketing Team

IDAs a...I want to...So that...
US-01Marketing managerCreate a modal that appears when anonymous readers try to leave the siteI can capture potential readers before they bounce
US-02Marketing managerSchedule a promotional banner to run during our spring sale (Mar 15 - Apr 1)The promotion runs automatically without manual activation
US-03Marketing managerSee how many readers clicked vs dismissed each surfaceI can optimize surface content and timing
US-04Marketing managerLink a 20% discount coupon to a subscription surfaceReaders see the discount and it auto-applies at checkout
US-05Marketing managerTarget a surface only to readers coming from our Facebook campaignI can create a consistent experience from ad to conversion
US-06Marketing managerDuplicate a high-performing surface and tweak it for a new campaignI can iterate quickly without recreating everything from scratch
US-07Marketing managerPause a surface temporarily during a site eventThe surface doesn't interfere with the event experience
US-08Marketing managerSee which device types and traffic sources drive the most conversionsI can allocate marketing budget more effectively

For Readers (Implicit)

IDAs a...I want to...So that...
US-09Anonymous readerNot see the same pop-up on every pageMy reading experience isn't annoying
US-10Anonymous readerBe able to dismiss a surface and not see it again for a whileI feel in control of my experience
US-11Registered readerNot see "Create Account" prompts after I've already registeredThe site recognizes who I am
US-12SubscriberNot see subscription prompts at allI'm not being asked to buy something I already have
US-13Mobile readerSee surfaces that work well on my phone screenThe promotion doesn't break my reading experience
US-14Reader with a coupon linkHave the discount auto-apply at checkoutI don't have to remember or type the code

For Editors/Content Team

IDAs a...I want to...So that...
US-15EditorPromote our new poetry anthology to readers browsing the poetry sectionThe promotion reaches readers most likely to be interested
US-16EditorShow an inline embed about our literary event within article pagesThe promotion feels editorial, not like an ad

20. Use Cases & Scenarios

Scenario 1: Converting Anonymous Visitors to Registered Readers

Setup: Create a modal surface with:

  • Goal: register
  • Audience: anonymous only
  • Trigger: exit_intent (desktop) / scroll_depth 75% (mobile fallback)
  • Frequency: Once per day
  • Suppress after dismiss: 3 days
  • Suppress if converted: Yes

Reader experience:

  1. Anonymous reader visits the site and reads an article
  2. When they move their mouse to close the browser tab, the modal appears
  3. "Create your free account — Save articles, get personalized recommendations"
  4. If they register, the modal never appears again
  5. If they dismiss, it won't reappear for 3 days

Scenario 2: Subscription Conversion with Discount

Setup: Create a slide-in surface with:

  • Goal: subscribe_paid
  • Audience: anonymous, registered
  • Trigger: after_article_read
  • Linked coupon: "SAVE30" (30% off first year)
  • Linked plan: Premium Annual
  • Frequency: Once per week
  • Suppress if converted: Yes

Reader experience:

  1. Reader finishes reading an article
  2. Slide-in appears: "Enjoyed this? Subscribe and save 30% — Use code SAVE30"
  3. Reader clicks "Copy Code" — code copied, GA4 coupon_copied event fires
  4. Reader clicks "Subscribe Now" — redirected to /subscribe/checkout?plan=premium-annual&coupon=SAVE30
  5. Checkout page auto-fills "SAVE30" in the promo code field
  6. Price updates to show 30% discount

Scenario 3: Time-Limited Campaign Promotion

Setup: Create a top banner surface with:

  • Goal: view_campaign
  • Audience: All
  • Trigger: page_load
  • Schedule: March 15 to April 1
  • Linked campaign: "Spring Literary Festival"
  • Frequency: Once per session
  • Priority: 25 (high, to override other surfaces)

Lifecycle:

  1. Admin creates the surface on March 10 with status draft
  2. Admin reviews content and sets status to scheduled with startsAt = March 15
  3. On March 15, the cron job detects startsAt has passed and sets status to active
  4. Readers see the banner: "Spring Literary Festival starts now! Join 20+ sessions with leading authors"
  5. On April 1, the cron job detects endsAt has passed and sets status to expired
  6. Banner stops appearing automatically

Scenario 4: Newsletter Growth via Inline Embed

Setup: Create an inline embed surface with:

  • Goal: subscribe_newsletter
  • Audience: newsletter_unsubscribed
  • Page types: article only
  • Trigger: N/A (inline embeds render with the page)
  • Frequency: Once per day

Reader experience:

  1. Reader opens an article
  2. After the article content, between the article body and related content, an inline card appears
  3. "Enjoy stories like this? Get our weekly fiction digest in your inbox"
  4. Reader clicks "Subscribe" — newsletter sign-up flow triggers
  5. The embed doesn't appear again for 24 hours

Scenario 5: UTM-Targeted Social Media Promotion

Setup: Create a sticky notification with:

  • Goal: subscribe_paid
  • Audience: anonymous, registered
  • UTM targeting: utmSource: ["facebook", "instagram"]
  • Trigger: time_on_page (15 seconds)
  • Linked coupon: "SOCIAL25" (25% off)

Reader experience:

  1. Reader arrives from a Facebook ad (?utm_source=facebook)
  2. After 15 seconds of reading, a small sticky notification appears in the bottom-right
  3. "Welcome from Facebook! Get 25% off your subscription — SOCIAL25"
  4. Reader clicks "Copy Code" and proceeds to subscribe
  5. Readers arriving from Google, email, or direct visits never see this surface

Internal — QA, Testing & Limitations
21. QA Test Scenarios — Comprehensive Checklist
A. Surface Creation & Management
#ScenarioExpected Result
A1Create surface with all required fields onlySurface created in draft status
A2Create surface with all fields filledAll fields persisted correctly
A3Attempt to create surface without required fields400 error with validation details
A4Edit surface — change title and priorityUpdates saved, updatedBy recorded
A5Duplicate surfaceNew surface created with "(Copy)" suffix, stats reset to 0, status = draft
A6Archive surfaceStatus set to archived, no longer visible to readers
A7Attempt invalid status transition (archived -> active)400 error: "Invalid status transition"
A8Activate surface (draft -> active)Surface starts appearing to eligible readers
A9Pause active surfaceSurface stops appearing immediately
A10Resume paused surfaceSurface starts appearing again
A11Create surface with linked couponCoupon details visible on surface
A12Seed template surfaces15 draft surfaces created (skips existing names)
B. Scheduling & Lifecycle
#ScenarioExpected Result
B1Schedule surface with future startsAtStatus = scheduled, not visible to readers
B2Wait for cron after startsAt passesStatus auto-transitions to active within ~15 minutes
B3Set endsAt on active surface, wait for cronStatus auto-transitions to expired
B4Activate surface without startsAtImmediately active
B5Create surface with startsAt in the pastShould activate on next cron run
C. Targeting Rules
#ScenarioExpected Result
C1Target audience: anonymous onlyNot visible to logged-in readers
C2Target audience: registered onlyNot visible to anonymous visitors or subscribers
C3Target audience: subscriber onlyNot visible to anonymous or non-subscriber readers
C4Target page type: article onlyNot visible on homepage, section pages, etc.
C5Target device: desktop onlyNot visible on mobile or tablet
C6Target UTM source: facebookNot visible to direct visitors or Google traffic
C7Exclude URL: /account/*Not visible on any account page
C8Empty targeting rules (all fields empty)Visible to ALL audiences, pages, devices
C9Target content section: fictionOnly appears on fiction article pages
D. Trigger Behavior
#ScenarioExpected Result
D1Trigger: page_loadSurface appears immediately on page load
D2Trigger: time_on_page (30s)Surface appears exactly after 30 seconds
D3Trigger: scroll_depth (50%)Surface appears when reader scrolls past 50% of page
D4Trigger: exit_intent (desktop)Surface appears when mouse moves toward browser close/back area
D5Trigger: page_view_count (3)Surface appears on the 3rd page view in session
D6Trigger: after_article_readSurface appears after reader reaches ~90% scroll + has spent time
D7Exit intent on mobileFallback to scroll-depth trigger
E. Frequency & Suppression
#ScenarioExpected Result
E1Frequency: 1/sessionSurface appears once, then not again in same session
E2Frequency: 1/daySurface appears once, then not again for 24 hours
E3Frequency: 3/weekSurface appears up to 3 times in 7 days
E4Dismiss then revisit (suppressAfterDismiss: 7)Surface does not reappear for 7 days
E5Click CTA (suppressAfterConversion: true)Surface never appears again for this reader
E6Already registered, surface goal=register (suppressIfConverted: true)Surface never appears
E7Clear localStorageFrequency state reset for anonymous readers
F. Coupon Integration
#ScenarioExpected Result
F1Surface with active couponCoupon code displayed, "Copy Code" button visible
F2Click "Copy Code"Code copied to clipboard, coupon_copied event recorded
F3Click CTA with coupon linkedURL has ?coupon=CODE appended
F4Arrive at checkout from surface CTAPromo code field auto-filled with coupon code
F5Coupon expiredSurface shows without coupon (coupon filtered out)
F6Coupon exhausted (max uses reached)Surface shows without coupon
F7Coupon inactiveSurface shows without coupon
G. Priority & Conflict Resolution
#ScenarioExpected Result
G1Two eligible surfaces with different prioritiesHigher priority surface shown
G2Two eligible surfaces with same priorityMore recently created surface shown
G3Modal (overlay) + Inline Embed both eligibleBoth shown — inline does not conflict with overlay
G4Two modals both eligibleOnly the higher-priority modal shown
H. Analytics & Tracking
#ScenarioExpected Result
H1Surface impressionimpressionCount incremented, GA4 impression event fired
H2CTA clickclickCount incremented, GA4 click event fired
H3Surface dismisseddismissCount incremented, GA4 dismiss event fired
H4Conversion completedconversionCount incremented, GA4 conversion event fired
H5Coupon copiedcoupon_copied event recorded (internal + GA4)
H6View stats in adminAll metrics, rates, time-series, and breakdowns display correctly
H7UTM params on CTA URLCTA URL contains utm_source, utm_medium, utm_campaign
H8Existing UTM params not overwrittenIf URL already has UTM, surface UTM is NOT added
I. Reader Portal Rendering
#ScenarioExpected Result
I1Modal on desktopCentered card with backdrop blur, X button, Escape key works
I2Modal on mobileBottom sheet slide-up
I3Sticky notificationSmall card in configured corner, X to dismiss
I4Slide-in panelFull-height panel from right, backdrop click to close
I5Top bannerFull-width strip at top, X to dismiss
I6Bottom bannerFull-width strip at bottom, X to dismiss
I7Inline embedCard within page content flow, no dismiss button
I8Surface on /login pageNOT displayed (suppressed page)
I9Surface on /account pageNOT displayed (suppressed page)
I10Surface on /subscribe pageNOT displayed (suppressed page)
J. Edge Cases
#ScenarioExpected Result
J1No eligible surfacesNothing displayed, no console errors
J2API failure (network error)Graceful degradation, no surface shown, no UI crash
J3Surface deleted while reader is on pageAlready-displayed surface continues; next page load doesn't show it
J4Reader logs in after seeing anonymous surfaceNext page load respects new audience state
J5Multiple rapid page navigationsNo duplicate surfaces or stacking
J6Browser back button after dismissalSuppression state preserved

22. Known Limitations
LimitationDescriptionWorkaround
No A/B testingCannot split-test two versions of the same surfaceCreate two surfaces with same targeting but different priorities; rotate manually
No geographic targetingCannot target by reader's country or regionUse UTM targeting to segment traffic sources
No admin previewNo way to preview exactly how a surface looks on the reader portal from the admin consoleActivate in draft on staging environment, or use low-priority test surface
Cron lag (up to 15 min)Scheduled start/end times execute within ~15 minute windowsFor exact-time activations, manually change status
Exit intent is desktop-onlyNo reliable exit intent signal on mobile browsersSystem falls back to scroll_depth on mobile
Anonymous frequency is client-sideClearing localStorage resets frequency caps for anonymous readersServer-side tracking only available for authenticated readers
Single surface per overlay typeOnly one modal/banner/slide-in/sticky per page loadUse priority to ensure the most important one wins

23. Glossary
TermDefinition
CTACall to Action — a button or link prompting the reader to take an action
CTRClick-Through Rate — percentage of impressions that result in a CTA click
Conversion RatePercentage of impressions that result in a completed conversion
Dismiss RatePercentage of impressions that result in the reader closing the surface
Engagement Rate(Clicks + Conversions) / Impressions
Frequency CapMaximum number of times a surface is shown within a time window
GA4Google Analytics 4 — the analytics platform used for tracking reader behavior
ISRIncremental Static Regeneration — Next.js caching mechanism
RBACRole-Based Access Control — permission system for admin users
SessionA single browser visit; ends when the browser tab is closed or after 30 minutes of inactivity
UTMUrchin Tracking Module — URL parameters used to track marketing campaign traffic sources

On this page

1. What Are Conversion Surfaces?2. Business Objectives3. Key Concepts & Terminology4. Surface Types — What Readers See4.1 Modal4.2 Sticky Notification4.3 Slide-In Panel4.4 Top Banner4.5 Bottom Banner4.6 Inline Embed5. Conversion Goals — What You Want Readers to Do6. Targeting Rules — Who Sees a Surface6.1 Audience Targeting6.2 Page Type Targeting6.3 Device Type Targeting6.4 Content Targeting (Advanced)6.5 URL Targeting (Advanced)6.6 UTM Targeting (Advanced)7. Trigger Rules — When a Surface Appears8. Frequency & Suppression — How Often a Surface Appears8.1 Frequency Capping8.2 Dismissal Suppression8.3 Conversion Suppression8.4 How Frequency State Is Tracked9. Scheduling & Lifecycle — When a Surface Is Active9.1 Status Lifecycle9.2 Allowed Status Transitions9.3 Automatic Transitions (Cron Job)9.4 Immediate Activation10. Priority & Conflict Resolution — Which Surface Wins11. Coupon Integration — Promo Codes on SurfacesWhat Happens When a Coupon Is LinkedExample Flow12. Entity Linking — Connecting Surfaces to Platform Entities13. Analytics & Tracking — Measuring Surface Performance13.1 Internal Analytics (ConversionEvent Table)13.2 Denormalized Counters13.3 GA4 Events13.4 Admin Stats Dashboard14. UTM Attribution — Tracking Marketing Source15. Reader Portal Rendering — How It All Works Together15.1 Architecture15.2 Rendering Flow15.3 Page Suppression16. Admin Console — Managing Surfaces16.1 Navigation16.2 List Page16.3 Create/Edit Form16.4 Permissions (RBAC)17. Pre-Built Templates — Getting Started Quickly18. Page Suppression — Where Surfaces Never Appear19. User StoriesFor Marketing TeamFor Readers (Implicit)For Editors/Content Team20. Use Cases & ScenariosScenario 1: Converting Anonymous Visitors to Registered ReadersScenario 2: Subscription Conversion with DiscountScenario 3: Time-Limited Campaign PromotionScenario 4: Newsletter Growth via Inline EmbedScenario 5: UTM-Targeted Social Media Promotion