Skip to content

Add popup runtime integration - #76

Open
anyelopetit wants to merge 2 commits into
mainfrom
feat/783-capture-popups-v1
Open

Add popup runtime integration#76
anyelopetit wants to merge 2 commits into
mainfrom
feat/783-capture-popups-v1

Conversation

@anyelopetit

@anyelopetit anyelopetit commented Aug 11, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds Capture Popup runtime support for Pop-ups on issue #783

The SDK can now mount a dashboard-configured popup on merchant websites, render the server-provided popup HTML, evaluate display rules client-side, handle bubble/open/close behavior, validate multi-step inputs, submit captured data, and show the completed state.

Issue

Capture Popups V1 now has a Rails-side builder, install flow, public render endpoint, and public submissions endpoint. The missing SDK piece was the storefront integration: hellotext.js needed to load the installed popup and make it behave like it would on a third-party merchant site.

Required runtime behavior:

  • Support automatic dashboard installation through public business metadata.
  • Support manual installation through explicit popup.id.
  • Mount server-rendered popup markup without duplicating Rails rendering logic.
  • Respect persisted layout, styles, header image, content, steps, bubble settings, coupon metadata, journey metadata, and rules.
  • Show the bubble first when bubble is enabled.
  • Open the popup after bubble click.
  • Validate required input fields before advancing steps.
  • Submit only after the final step.
  • Show the completed screen after successful submission.

Solution

Popup configuration

  • Added Configuration.popup.
  • Supported SDK config:
Hellotext.initialize('HELLOTEXT_BUSINESS_ID', {
  popup: {
    id: 'POPUP_ID',
    container: 'body',
    device: 'auto',
  },
})
  • popup: false disables popup mounting.
  • popup.container defaults to body.
  • popup.device defaults to auto.
  • Dashboard-provided business.popup config is merged with local config.popup.
  • Local popup.id can override the dashboard popup id.

Popup API

  • Added API.popups.get(id) for GET /v1/public/popups/:id.
  • Added API.popups.submit(id, data) for POST /v1/public/popups/:id/submissions.
  • Uses the existing public authorization pattern through Hellotext.headers.
  • Sends session, locale, and runtime device data when fetching.
  • Parses returned HTML and mounts the <article> root.

Popup model

  • Added SDK Popup model.
  • Fetches public popup HTML through API.popups.
  • Waits for the latest Hellotext stylesheet before mounting.
  • Appends the popup to the configured container.
  • Fails closed when the endpoint returns no HTML, the container is invalid/missing, or the stylesheet fails to load.

Popup runtime controller

  • Added hellotext--popup Stimulus controller.
  • Handles:
    • device targeting
    • AND-only display rules
    • page property checks for path, URL, and title
    • scroll-depth rules
    • viewed-popup rules through localStorage
    • storage-blocked browser fallback
    • bubble-first display
    • bubble click to open popup
    • close behavior with and without bubble
    • multi-step navigation
    • native input validation
    • final submission
    • completion state

Styles, docs, and types

  • Added public popup CSS to styles/index.css.
  • Registered the popup Stimulus controller in the SDK entrypoint.
  • Exported the SDK Popup model.
  • Added TypeScript definitions for popup config and public business popup metadata.
  • Documented popup installation in README.md.

Decisions And Trade-Offs

  • Rails owns popup markup and persisted rendering details.
  • hellotext.js owns browser behavior, validation, rules, mounting, and submission.
  • Runtime rules are evaluated client-side because scroll depth and viewed-popup state depend on browser state.
  • Rules MVP is AND-only.
  • Unknown/custom form fields stay in submission metadata.
  • Native browser validation is used instead of building a custom validation system.
  • localStorage failures do not crash the merchant page; viewed-popup checks fail open.
  • The SDK waits for the Hellotext stylesheet before mounting to avoid unstyled popup flashes.
  • Popup behavior is isolated behind optional popup config, so existing forms and webchat behavior remain unchanged.

Compatibility

Backward-compatible for existing SDK consumers:

  • Existing Hellotext.initialize(BUSINESS_ID) behavior remains valid.
  • If no popup is configured in dashboard metadata, no popup is loaded.
  • popup: false explicitly disables popup mounting.
  • Existing forms and webchat config paths are unchanged.
  • Existing WhatsApp widget config paths are preserved.
  • New CSS uses hellotext--popup prefixed classes.

Runtime dependency:

  • This SDK change expects Rails to expose:
    • GET /v1/public/popups/:id
    • POST /v1/public/popups/:id/submissions
    • business.popup in the public business payload for automatic installs

Data And Rollout

  • No SDK database changes.
  • Requires deploying the matching Rails popup public API before or with this SDK release.
  • Merchant sites using automatic install can continue calling:
Hellotext.initialize('HELLOTEXT_BUSINESS_ID')
  • Merchant sites using manual install can call:
Hellotext.initialize('HELLOTEXT_BUSINESS_ID', {
  popup: {
    id: 'POPUP_ID',
  },
})

Production Risks

  • Public popup rendering depends on the Rails endpoint returning valid HTML.
  • The SDK intentionally does not mount if the stylesheet cannot load.
  • Browser-specific validation messages are native and may vary by locale/browser.
  • Rules are client-side only, so server-side display enforcement is not part of this PR.
  • OR groups, Automations, Timing filters, coupon delivery, and resend behavior remain follow-ups.

Pre-Deploy Checklist

  • Confirm the matching Rails PR is deployed or ready to deploy.
  • Confirm /v1/public/popups/:id returns popup HTML for an active visible popup.
  • Confirm /v1/public/popups/:id/submissions accepts email and phone submissions.
  • Build/package the SDK.
  • Publish the SDK version.
  • Smoke-test manual installation with explicit popup.id.
  • Smoke-test automatic installation with dashboard business.popup.

Post-Deploy Checklist

  • Mount a popup on a staging merchant page.
  • Verify bubble-first behavior.
  • Verify close returns to bubble when bubble is enabled.
  • Verify close hides the popup when bubble is disabled.
  • Verify mobile and desktop rendering.
  • Verify header image, colors, layout, button alignment, and footer layout.
  • Verify multi-step validation and advancement.
  • Verify final submission creates or updates a popup submission.
  • Verify completion screen appears after successful submit.
  • Monitor browser console errors around hellotext--popup.
  • Monitor API errors for public popup render and submissions.

Test Verification

Focused SDK tests passed:

yarn test __tests__/api/popups_test.js __tests__/models/popup_test.js __tests__/controllers/popup_controller_test.js __tests__/core/configuration_test.js __tests__/hellotext_test.js __tests__/api/whatsapp_widgets_test.js __tests__/core/whatsapp_configuration_test.js __tests__/models/whatsapp_widget_test.js

Result:

Test Suites: 8 passed, 8 total
Tests: 80 passed, 80 total

Additional checks:

node --check src/hellotext.js
node --check src/controllers/popup_controller.js
git diff --cached --check

Manual Verification

Recommended manual flow:

  1. Create and publish a popup in Rails.
  2. Confirm automatic install writes business.metadata.pixel.popup.id.
  3. Load a merchant page with Hellotext.initialize(BUSINESS_ID).
  4. Confirm the popup mounts from dashboard metadata.
  5. Repeat with explicit popup.id.
  6. Confirm rules block/display the popup as expected.
  7. Confirm bubble opens the popup.
  8. Complete all steps with valid data.
  9. Confirm invalid inputs block step advancement.
  10. Confirm successful submit shows completion.

Follow-Ups

  • Full staging embed QA against a real merchant page.
  • OR rule groups.
  • Automations and Timing filters.
  • Coupon delivery and resend flows.
  • Optional CSS deduplication with the Rails public popup stylesheet if maintenance cost grows.

Note

Medium Risk
New customer-facing capture UI that mounts on merchant sites and submits PII (email/phone), but it follows existing webchat/widget patterns and is opt-in/backward compatible.

Overview
Adds Hellotext Popups so merchant sites can mount dashboard-configured capture popups at initialize time.

Popups load from dashboard business.popup metadata or an explicit popup.id, with popup: false to disable. Local options (container, device) merge over dashboard defaults. The SDK fetches server-rendered HTML, waits for styles, and mounts into the configured container.

A new hellotext--popup controller handles bubble/open/close, device targeting, AND display rules (page properties, scroll depth, viewed state), multi-step validation, submission, and the completed state.

Reviewed by Cursor Bugbot for commit a3adf5c. Bugbot is set up for automated code reviews on this repo. Configure here.

@anyelopetit
anyelopetit requested a review from rockwellll August 11, 2026 23:41
@anyelopetit anyelopetit self-assigned this Aug 11, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 8b78c1d. Configure here.

Comment thread src/controllers/popup_controller.js
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant