# @blotoutio/providers-blotout-popup-sdk

Browser-side Blotout Popup runtime for EdgeTag. Renders popup rules authored in the
Blotout Popup dashboard into the merchant storefront — modal, slide-in, bar, floating
box, fullscreen takeover, and cart drawer formats.

## Loading

The CDN worker emits the bundle URL on every storefront page-load when the
provider's `uiPreferences.mode` is `enabled` or `preview`. The bundle's `init`
entry point reads `manifest.variables.popupRules`, picks the first rule whose
conditions, schedule, and fatigue all pass, and appends the rendered popup to
`document.body` — except the `cartDrawer` format, which mounts in normal flow
inside the theme's own cart container above the checkout block. With no
container found it falls back to a floating box while the shopper is in the
cart, and does not render at all anywhere else.

## Events

The SDK dispatches custom DOM events on the popup root for host integrations:

| Event                       | Detail                                |
| --------------------------- | ------------------------------------- |
| `blotoutpopup:submit`       | `{ ruleId, formData, integrations? }` |
| `blotoutpopup:dismiss`      | —                                     |
| `blotoutpopup:gotostep`     | `{ ruleId, stepId }`                  |
| `blotoutpopup:couponcopied` | `{ ruleId, code }`                    |

## Fatigue + Schedule

Per-rule impression count, dismiss state, and conversion state are persisted
to `sessionStorage` or `localStorage` (keys prefixed `blotoutpopup:fatigue:`) based
on the rule's `fatigue` settings. The `schedule` window is re-checked at fire
time.

## CSP

The SDK appends a `<style>` element to `document.head` for keyframe animations
and, when the rule defines `rule.css`, appends a second `<style>` inside the
popup root. Storefronts with `style-src 'self'` (no `unsafe-inline`) will
block both — keyframe animations and merchant CSS won't apply.
