Guides
Multi-Step Modal Flows
Build a sequence of steps inside a single modal — teasers, email capture, coupon reveals, countdowns, and confirmation screens — all wired to Adobe Target events.
Multi-step mode turns a single popup into a guided flow. Each step can be a different type and navigates independently. Trigger, frequency, and style settings apply to the whole modal — only content varies per step.
Building a flow — step by step
This walkthrough builds a 3-step teaser → email → confirmation flow. The same steps apply to any combination of step types.
Steps
Navigation
Enable Multi-step mode
Add and configure steps
Add a back button (optional)
Set progress indicator and transition
Name your events
modalFlowComplete) and Step View Event Name (fires on each step transition with detail.step and detail.total — default: elStepView). To catch events while testing, paste window.addEventListener('modalFlowComplete', e => console.log(e.detail)) in the console before the script.Generate and test
Steps
Navigation
Step types
Content
Headline, body text, and a CTA button. The CTA action can advance to the next step, navigate to a URL, or close the modal. Use as a teaser, offer reveal, or any informational screen.
An email capture form within the flow. On successful submission, it automatically advances to the next step after a brief confirmation moment. No CTA action needed.
💡 Place the email step after a teaser — visitors who see value first are more likely to share their email.
Confirmation
A thank-you or success screen. Typically the last step. CTA action defaults to Close.
💡 Keep the message brief and specific — "You're in! Check your inbox for 20% off" beats "Thank you for subscribing."
Coupon
Displays a prominent coupon code with a one-click copy button. Visitors copy the code without leaving the page.
💡 Pair with urgency copy on the preceding Content step: "Expires tonight" or "First 100 only."
Countdown
Displays a live countdown timer (hours : minutes : seconds). Optional auto-advance: when the timer expires, automatically moves to the next step with no click required.
💡 Use Auto-advance to transition from a countdown into an email capture step — the urgency carries straight into the form.
Image
A full-width image with optional caption and CTA button. Good for product reveals, before/after comparisons, or brand imagery.
Use cases by industry
Real-world flow patterns for five verticals. Pick the one closest to your audience and adapt it.
Flash sale discount delivery
Build anticipation, then deliver the reward.
Black Friday early access
Be the first to grab 25% off everything.
Why it works: Visitors who click through the teaser are already committed, making the coupon feel earned rather than given.
Cart abandonment recovery
Urgency drives the capture; confirmation keeps the brand warm.
Your cart is reserved
Items expire in
Why it works: The countdown primes urgency before the email ask, lifting conversion rates on the form.
New product launch
Tease the reveal, capture the list, confirm the wait.
Introducing the Aria 2
First 500 buyers get exclusive launch access.
Why it works: Sequenced reveals build anticipation better than a single announcement.
Resume from last step
When a visitor closes the modal mid-flow and returns later, the modal automatically reopens at the step they reached — not step 1. The resume position is stored in localStorage and cleared only when the visitor completes all steps (fires the completion event).
Adobe Target integration
Both events fire as CustomEvent on window. Adobe Tags can listen for them with a Direct Call rule.
Track flow completion as a conversion
Two ways to wire up the conversion — pick whichever fits how the rest of your activity is set up.
Add a conversion metric in Adobe Target
In your activity, go to Goals & Settings → Metrics. Add a metric: Goal = Conversion, Action = Clicked an element. In the CSS selector field enter #_atlastcta — the generated script assigns this ID to the final step's CTA button.
Adobe Target · Activity
Goals & SettingsReporting Settings
Goal metric *
The Experience Lab script auto-assigns #_atlastcta to the final step's CTA — paste it directly into the element selector. No manual hunting required.
Additional metrics
Configure other success metrics for reporting.
Or use Experience Lab's Until Conversion frequency
In Experience Lab's modal builder, open the FREQUENCY section and choose Until conversion. Then in BEHAVIOR, set the Completion Event Name — the script's built-in localStorage suppression handles the rest. The modal re-shows on every visit until the visitor completes the flow, then stops permanently. Adobe Target only deploys the script — no conversion metric, no goal setup, and nothing to wire up on the Target side.
Experience Lab · Modal builder
SidebarFrequency
One of nine frequency categories in the dropdown. No extra fields appear when this is selected.
How conversion is detected
- ·Single-step modal: CTA click marks the visitor converted.
- ·Multi-step modal: completing the final step fires the
Completion Event Namefrom the BEHAVIOR section, which the script listens for and writes a permanent localStorage flag. - ·On every subsequent visit the script reads the flag and returns early — the modal never renders again for that visitor.
modalFlowComplete event in an Adobe Tags rule and fire a custom link or XDM payload — the setup is identical to the Step View tracking covered in Step-level analytics below; just swap the rule's identifier from elStepView to modalFlowComplete.Step-level analytics
Adobe Target reports tell you which whole flow won. To see where visitors drop off mid-flow, capture the elStepView event in your tagging tool and send it to your analytics platform. The event fires on every transition with detail.step (0-based) and detail.total. Pick the implementation below that matches your stack.
Decision · which option fits you
On AppMeasurement (s_code), reporting in AA Workspace
Most legacy stacks. s.tl(), eVars, and props all work as-is.
Migrated to Web SDK (Alloy), still reporting in AA Workspace
The _experience.analytics mapping keeps your existing eVar/prop/event reports alive — no rebuild needed.
Reporting in CJA (with or without AA running alongside)
AEP-native. A custom XDM field group makes step index a first-class CJA dimension — no eVar mapping required.
s.tl() and/or CJA alloy("sendEvent", …) calls inline — no Adobe Tags rule needed for the basics. Open the ANALYTICS section in the modal sidebar, pick a platform, fill in your slots / tenant, and the generated script ships with tracking baked in. The Tags-rule walkthroughs below are still the right path for teams that want hybrid _experience.analytics mapping or step-level reporting beyond what the built-in shape covers.Setting it up — step by step
Five clicks from a fresh modal to a fully tracked flow. The mockup on the right updates as you scroll — or click any step to jump.
Open ANALYTICS
Pick a platform
s.tl() calls), CJA (inline alloy("sendEvent")), or Both (parallel calls — for hybrid teams running AA Workspace and CJA off the same Web SDK). The fields below appear only after you pick a non-None value.Set Modal Name
q4-lead-capture the script fires q4-lead-capture-step-1, q4-lead-capture-cta-2, q4-lead-capture-complete, etc. Auto-defaults to a hyphen-slug of your headline the first time you flip Platform off None — feel free to overwrite.Fill slots / tenant
eVar10), the event counter slot (event42), and the completion success event slot (event43). For CJA: enter your AEP tenant ID (e.g. citynationalbank). Don't know your tenant? Hit the 🔍 Auto-detect from URL affordance below the field — paste any page on your site that loads Adobe Tags and the server-side detector returns it.Generate and verify
if(typeof s!=="undefined")… and/or alloy("sendEvent")… guarded calls. To smoke-test live: open your test page, paste the script in DevTools console, click through the modal, and watch the Network tab for /b/ss (AA) or /interact (Web SDK) beacons firing for each event.What fires when
For a typical 3-step Content → Email → Confirmation flow, here's the exact event sequence the script emits to AA and/or CJA:
What fires when
Event sequence for a 3-step flow (Content → Email → Confirmation)
- 1
Modal opens at Step 1 (Content teaser)
stepViewstep 1 of 3q4-lead-capture-step-1 - 2
Visitor clicks Step 1 CTA
ctaClickstep 1 of 3q4-lead-capture-cta-1 - 3
Step 2 (Email capture) renders
stepViewstep 2 of 3q4-lead-capture-step-2 - 4
Visitor submits the email form
ctaClickstep 2 of 3q4-lead-capture-cta-2 - 5
Email validated successfully
emailSubmitq4-lead-capture-email-submit - 6
Step 3 (Confirmation) renders
stepViewstep 3 of 3q4-lead-capture-step-3 - 7
Visitor clicks final CTA
ctaClickstep 3 of 3q4-lead-capture-cta-3 - 8
Flow completes, modal closes
completeq4-lead-capture-complete
s.tl() call and a CJA alloy("sendEvent") call when Platform = Both. For dismiss events (close button, overlay, Escape) — not shown above — the same pattern applies; a dismissed flow fires q4-lead-capture-dismiss instead of the remaining step / cta / complete events.eVar10, prop10, event42, and event43 as illustrative slots. Every Adobe Analytics report suite numbers its own slots independently — substitute whichever eVar / prop / success event positions are free in your environment. Before they capture data, make sure the chosen slots are enabled and named in Admin → Report Suite Settings → Conversion / Traffic / Success Events. Option C (CJA) uses XDM field groups instead of numbered slots, so this only applies to Options A and B.Option A — AppMeasurement (legacy s_code)
Standard for sites still on AppMeasurement. Build an Adobe Tags rule with Event = Custom Event, identifier = elStepView, then add this Custom Code action.
// Replace eVar10, prop10, event42 with free slots in your report suite. var stepIndex = event.detail.step; // 0-based (0 = step 1) var total = event.detail.total; var label = 'q4-lead-capture-step-' + (stepIndex + 1); if (typeof s !== 'undefined') { s.linkTrackVars = 'prop10,eVar10,events'; s.prop10 = label; s.eVar10 = label; s.events = 'event42'; // counter: modal step viewed s.tl(true, 'o', 'Modal Step View'); }
Option B — Web SDK (Alloy)
If you've migrated to Web SDK, replace the s.tl call with alloy("sendEvent", ...). Map the step into legacy Analytics variables under _experience.analytics so existing Workspace reports keep working — same eVar/prop/event numbers as before.
// Replace eVar10, prop10, event42 with free slots in your report suite. // event1to100 covers events 1–100; use event101to200 / event201to300 // for higher-numbered slots. var stepIndex = event.detail.step; var total = event.detail.total; var label = 'q4-lead-capture-step-' + (stepIndex + 1); alloy("sendEvent", { type: "web.webinteraction.linkClicks", xdm: { eventType: "web.webinteraction.linkClicks", web: { webInteraction: { name: label, type: "other", linkClicks: { value: 1 } } }, // Map to legacy AA variables — keeps existing Workspace reports working _experience: { analytics: { customDimensions: { eVars: { eVar10: label }, props: { prop10: label } }, event1to100: { event42: { value: 1 } } } } } });
Without writing JavaScript — use the Send Event action
If you prefer the Tags rule UI to writing Custom Code, the setup is three pieces: (1) a Custom Code Data Element that returns the XDM object, (2) a Rule with a Custom Event trigger listening for elStepView on document, and (3) a Send Event action on that rule that fires Alloy with the XDM. Walk-through:
Create a Data Element
Tags · Data Elements · NewThe data element holds the XDM payload the action will send. Tags looks up data elements by name, so build this before the rule that references it.
Tags > cnb.com > Data Elements > New
// `event` is the elStepView CustomEvent on document var step = event.detail.step; var total = event.detail.total; return { eventType: "modalFlow.stepView", timestamp: new Date().toISOString(), _yourtenant: { modalFlow: { flowName: "q4-lead-capture", stepIndex: step, totalSteps: total, action: "stepView" } } };
Create the Rule
Tags · Rules · NewOne rule that listens for the modal's elStepView custom event (the trigger) and runs the Send Event action (the payload).
Tags > cnb.com > Rules > New
IF — when to fire
Core — Custom Event
elStepViewElement: documentTHEN — what to do
Adobe Experience Platform Web SDK — Send event
Configured next ↓
Configure the Send Event action
Tags · Edit ActionClick the action card from Step 2 to open this form. Reference the data element from Step 1 in the XDM field on the right.
Tags > cnb.com > Rules > Modal step view → CJA > Action Configuration
Auto-populated from the action type. Leave it as-is or rename for clarity in the rule list.
The Web SDK instance name from your extension config. Often alloy (matches the global function) — yours might be different.
Auto-fills or hides certain fields for specific use cases (e.g. page view, link click). Leave unchecked for our custom flow event.
Data
Optional override. Skip this — the eventType is already inside the XDM object the data element returns.
Click the database icon → pick the xdm.modalStepView data element you built in Step 1. This is where Adobe Tags pulls the actual XDM object from.
Optional non-XDM payload. Leave empty.
Option C — Customer Journey Analytics (CJA)
CJA reports on AEP datasets, not eVars. Web SDK already lands events in your event dataset — for clean, queryable step data, define a custom XDM field group for modal flows and populate it on every send. This makes step index a first-class dimension in CJA workspaces, no eVar mapping needed.
Add a custom XDM field group in AEP
In Experience Platform → Schemas, open your event schema and add a field group _yourtenant.modalFlow with fields: flowName (string), stepIndex (integer, 0-based), totalSteps (integer), and action (string — values: stepView, complete).
Send the XDM payload from your Tags rule
Replace yourtenant with your AEP tenant ID. The legacy AA mapping is optional — include it only if you also report in AA Workspace.
Build the funnel in CJA
Open a CJA workspace project, drag in the connection, add a Fallout visualization with Modal flow → Step index as the touchpoint dimension. Each value (0, 1, 2…) becomes a step in the funnel automatically.
Here's what the field group looks like in the AEP schema editor once it's saved:
Adobe Experience Platform · Schemas
Edit field groupSchema
Web Events Schema
Class
XDM ExperienceEvent
Properties
Field group saved · enable on dataset to start collecting
v 1.0Where to find your AEP Tenant ID
The tenant ID is the short lowercase string Adobe Experience Platform uses to namespace your org's custom XDM fields — it's the prefix in paths like _yourtenant.modalFlow.stepIndex. It's typically a shortened version of your company name (e.g. acmecorp, cnb, cjmcybs). It is not the IMS Org ID, the Dataset ID, the sandbox name, or the Datastream ID.
Open AEP → Schemas → Browse
Click any custom field group your team has created. In the schema field tree, expand any group — paths starting with _yourtenant.something reveal the prefix. The string between the leading _ and the first . is your Tenant ID.
Or check the AEP Web SDK extension config in Tags
Adobe Tags → your property → Extensions → Adobe Experience Platform Web SDK → Configure. The configured XDM data element type or the Datastream config often surfaces the tenant prefix.
Or fire a test alloy() call and inspect the network beacon
On a page where Web SDK is already loaded, run alloy("sendEvent", { xdm: { eventType: "test" } }); in the console. Open the Network tab, find the /interact request, expand the payload — the tenant prefix appears in the XDM path.
Or just ask your data engineering team
If you don't have direct AEP UI access, the team that owns your Adobe Experience Platform implementation can answer in 30 seconds. Tell them: "I need our AEP Tenant ID for an XDM custom field group."
Or use the auto-detect tool in the modal builder
The modal builder's ANALYTICS section has a Auto-detect from URL affordance — paste any page on your site that has Adobe Tags loaded, and it'll fetch the Tags container and extract the tenant prefix automatically.
- IMS Org ID — long format like
2DD68785558BD0AB7F000101@AdobeOrg. Identifies your Adobe org globally; used in API auth and SDK init. Sometimes the tenant prefix is a transliteration of the company name in this org, but the IDs themselves are independent. - Datastream Config ID — UUID like
691e8bad-1502-4169-896d-bb5538df3261. Identifies which datastream your Web SDK forwards data through. Visible in theconfigIdquery param of every/interactcall. - Edge endpoint hostname — sites with first-party CNAMEs route Web SDK traffic through their own domain (e.g.
smetrics.yoursite.com/ee/v1/interact) instead ofedge.adobedc.net. This is a delivery detail — has no bearing on the tenant. - Sandbox name — typically
prod,dev, orstage. Identifies which AEP environment your data lands in. Each sandbox has its own datasets and schemas, but they share the same tenant prefix across the org.
alloy("sendEvent", { xdm: { eventType: "modalFlow.stepView", timestamp: new Date().toISOString(), web: { webPageDetails: { URL: window.location.href, name: document.title } }, _yourtenant: { modalFlow: { flowName: "q4-lead-capture", stepIndex: event.detail.step, // 0-based totalSteps: event.detail.total, action: "stepView" } } } });
Build the funnel in Workspace
Same setup whether you're in Adobe Analytics Workspace or CJA — only the dimension source differs.
Drag in a Fallout visualization
From the Visualizations panel of a new project. Workspace also accepts a fallout from a freeform table — use whichever you prefer.
Set the Touchpoint dimension
AA Workspace: whichever eVar you populated above (e.g. eVar10 — substitute your own slot). CJA: your custom Modal flow → Step index XDM dimension.
Drop one filter per step
AA: drop the eVar value for each step (q4-lead-capture-step-1, …-step-2, …-step-3). CJA: drop stepIndex = 0, 1, 2.
Add a converter segment (optional but powerful)
Filter the fallout on the completion success event (e.g. event43 — substitute your own slot) in AA, or action = complete in CJA) to compare paths of converters vs. abandoners side-by-side.
Read the curve
Each bar shows the conversion rate from one step to the next. Steep drops at Step 2 usually mean friction in the email field. Drops at the final step usually mean weak CTA copy or an unclear value reveal. This becomes an actionable report — every drop-off point is a hypothesis the Adobe Target team can test next: shorter copy at Step 1, fewer fields on the email step, a stronger value reveal before the final CTA. Run those as A/B activities against the same funnel and each iteration compounds the lift.
🪜 Need help wiring up a multi-step flow end to end?
Experience Lab can design the step sequence, configure Adobe Target conversion tracking, and set up Adobe Analytics funnel reporting — so you can measure every step of your flow from day one.