Conversion Funnels in Admaxxer — cohort-aware, revenue-quantified, multi-source
A conversion funnel is a multi-step user journey from landing to value moment, with drop-off measured at each step. Admaxxer's funnel builder takes the same primitive that Datafast and Plausible expose, then layers on four things they don't: cohort-aware filtering, revenue-per-step quantification, multi-source attribution at every step, and a time-to-conversion distribution. The result is a funnel report that not only tells you where users drop off, but exactly how many dollars are stuck behind each drop-off and which channel's audience is leaking worst.
What is a conversion funnel?
A conversion funnel is an ordered sequence of 2 to 5 steps representing the path a visitor must take to reach a value moment. The classic e-commerce funnel is Land → Product → Cart → Checkout → Purchase. The classic SaaS funnel is Land → Pricing → Trial → Activation → First Revenue. Each step is satisfied by an event — a pageview matching a URL pattern, a custom goal call, or a revenue event — and each visitor either reaches that step or drops off.
The funnel report tells you three things at a glance: the drop-off rate at each transition (what percentage of users who reached step N never reach step N+1), the overall conversion rate (final-step count divided by first-step count), and a step-1 entry source breakdown (which channel sent the visitors who entered the funnel). On top of that, Admaxxer adds revenue, cohort, and time-to-conversion layers — explained below.
Building a 2 to 5 step funnel in Admaxxer
Admaxxer funnels are flexible by design — each step can be defined three different ways, and you can mix definitions inside a single funnel. The three step types are:
- Page URL. The step fires when the visitor's pageview matches a URL pattern. Patterns support exact match (
/checkout), prefix match (/products/*), and query-string-stripped match (/pricingignores?utm_source=...). Path-normalization rules (trailing-slash stripping, hash stripping) are applied at ingest, so/products,/products/, and/products#reviewsall match a single/productsrule. See the path-normalization section in /documentation/dashboard/analytics for the full rules. - Custom goal. The step fires when the visitor's session triggers a named goal — either an auto-tracked Admaxxer goal (
__admx_signup,__admx_add_to_cart,__admx_email_capture,__admx_checkout_completed) or any merchant-defined goal fired viatrack('your_goal_name')from your storefront. Goals are the right primitive when the value moment isn't a pageview — e.g., a button click, a form submission, or a SPA state change that doesn't update the URL. See /documentation/custom-goals for the full goal-creation flow. - Revenue event. The step fires when the visitor's session is associated with a revenue event of any value — Custom Pixel
checkout_completed, admin-webhookorders/paid, or a direct revenue webhook (Stripe / Paddle / Polar / Lemon Squeezy / Dodo). Revenue events are the natural last step in any e-commerce funnel and are required for the revenue-per-step layer to populate.
You can mix and match: a SaaS funnel might be Land (page) → Pricing (page) → Click Trial (goal) → Activate Trial (goal) → First Revenue (revenue event) — three different step types in one funnel. The builder doesn't care about the type; it cares about the order.
UI walkthrough
The funnel builder lives on the dashboard alongside every other analytics card. To create a new funnel:
- Open /dashboard/analytics and scroll to the Funnels card under Advanced.
- Click + New Funnel. A side-drawer opens.
- Name the funnel (e.g., “Marketing Acquisition Funnel”). Names are workspace-scoped and shared across team members.
- Add steps one at a time. For each step, choose the type (page / goal / revenue), then enter the matcher (URL pattern, goal name, or “any revenue event”).
- Optionally, apply step-level filters: UTM source, UTM medium, device class (mobile / tablet / desktop), country (ISO-3166 alpha-2), traffic-source channel (Direct / Organic / Paid Social / Paid Search / Email / Referral). Filters are applied at the step, not the funnel as a whole.
- Pick a cohort scope (see the cohorts section below).
- Save. The funnel computes asynchronously over the last 7 days by default; first results land in single-digit seconds for <10M-event workspaces and within ~30 seconds at the upper bound.
Funnels are read-only for non-owner team members by default — owners and members with the analytics:write scope can edit; everyone else sees the saved funnel and the latest computed report.
Reading the funnel report
A populated funnel report shows four things stacked top-to-bottom:
- Step bars with absolute counts and drop-off percentages. Each step renders a horizontal bar sized proportional to the count of visitors who reached that step. Below the bar, the drop-off rate from the previous step is rendered in red (e.g., −65% means 65% of visitors who reached step N−1 never reached step N). The first step has no drop-off rate (it's the entry).
- Headline conversion rate. Final-step count divided by first-step count, expressed as a percentage. A 6% conversion rate on a 5-step funnel means 6 out of every 100 visitors who entered the funnel reached the value moment.
- Median time-to-conversion. The median elapsed time from a visitor's first-step event to their last-step event. Useful for setting attribution-window expectations — if your median time-to-conversion is 18 hours, a 1-hour attribution window is too short. See /documentation/troubleshoot/attribution-discrepancies for the attribution-window discussion.
- Step-1 entry source breakdown. The first step of every funnel reports the channel mix of the visitors who entered it: Direct, Organic, Paid Social, Paid Search, Email, Referral. Paid sources are determined from the Tinybird
attributed_utm_sourcecolumn populated at pageview ingest from the visitor's first-touch UTMs. Organic is determined heuristically from the referrer domain (Google, Bing, DuckDuckGo). Direct is the residual — no UTMs and no recognized referrer.
Example: a 5-step SaaS funnel
Consider the funnel Land → View Pricing → Click Trial → Activate Trial → First Revenue over a 30-day window:
| Step | Definition | Visitors reached | Drop-off from prior | Cumulative conversion |
|---|---|---|---|---|
| 1. Land | Any pageview with no prior session | 50,000 | — | 100% |
| 2. View Pricing | Page /pricing |
5,000 | −90% | 10% |
| 3. Click Trial | Goal start_trial_clicked |
1,500 | −70% | 3% |
| 4. Activate Trial | Goal __admx_signup |
1,050 | −30% | 2.1% |
| 5. First Revenue | Any revenue event | 180 | −83% | 0.36% |
The headline tells you: 0.36% land-to-revenue conversion. The drop-off pattern tells you the worst leaks are step 1 → 2 (−90% — most landers never view pricing) and step 4 → 5 (−83% — most trial activators never pay). Those are your two highest-leverage optimization targets.
Cohort segmentation — Admaxxer-unique vs. Datafast
Datafast funnels apply a single global filter set to all funnel viewers; you can scope by date, UTM, and device, but you cannot ask “show me this funnel for first-time visitors only” or “show me this funnel for users in the top-LTV decile.” Admaxxer funnels do.
Every funnel has a cohort scope dropdown that determines which visitors are eligible to enter the funnel:
- All visitors — the default. Every visitor who satisfies step 1 enters the funnel.
- First-time visitors only — only visitors whose
visitor_idfirst appeared inside the funnel's date window. Useful for measuring acquisition funnels in isolation from returning-customer behavior. - Returning visitors only — the inverse: only visitors with prior pageviews before the date window. Useful for measuring re-engagement and re-purchase funnels.
- Came from Meta ads / Came from Google ads / Came from TikTok ads — only visitors whose first-touch UTM source matches the chosen paid platform. Lets you compare paid-channel funnel performance side-by-side.
- Came from Organic search — only visitors whose first-touch referrer is a recognized search engine (Google, Bing, DuckDuckGo) and whose first-touch UTM source is empty.
- Top-LTV decile — only visitors whose 90-day projected LTV (from the
p_ad_ltvpipe) is in the top 10% of all visitors. Lets you ask “what does the funnel look like for the customers who actually matter?” - Geo-bounded — restrict to one or more countries or cities.
Cohort filters are applied at the visitor level, not at the step level. A returning-only funnel doesn't only count returning visitors at step 3; it requires the visitor to be a returning visitor for them to be eligible to enter step 1 in the first place. The denominator at every step is consistent.
Side-by-side: running the same 5-step funnel scoped to First-time visitors vs. Top-LTV decile typically reveals dramatic differences. Top-LTV cohorts often have step-2 conversion 3-5x higher than first-time cohorts, and a much shorter time-to-conversion distribution. That delta is the signal you can't see in a Datafast funnel.
Revenue-per-step quantification — Admaxxer-unique
When the final step of a funnel is a revenue event, Admaxxer surfaces a revenue rescued column at every step. The math is straightforward: hold downstream conversion rates constant, increase the conversion rate at step N by some delta, and report the additional revenue that would land at the final step.
Worked example: 1,000 visitors hit /pricing, 200 hit /checkout, 60 reach /thank-you for $6,000 in revenue (average order value $100). The current pricing-to-checkout rate is 20% and the checkout-to-revenue rate is 30%.
- If you improve pricing-to-checkout from 20% to 25% (a 5-point lift), 250 visitors hit checkout instead of 200. Holding the 30% checkout-to-revenue rate constant, that's 75 revenue events instead of 60. Revenue rescued: $1,500.
- If you improve checkout-to-revenue from 30% to 35% (a 5-point lift), 70 revenue events instead of 60. Revenue rescued: $1,000.
The funnel report renders these rescued-revenue numbers next to each step, so you can immediately see which step has the highest revenue-leverage on a 5-point conversion lift. This is the single most important number for deciding where to invest optimization effort, and Datafast doesn't surface it.
Caveats:
- The calculation assumes downstream rates hold — in practice, conversion rates often co-vary, so the rescued number is an upper-bound estimate, not a guaranteed lift.
- The 5-point delta is a configurable constant on the Funnels card; you can swap it for 1-point, 2-point, or 10-point to model larger interventions.
- Revenue is reported in the workspace's reporting currency (see /documentation/architecture/multi-currency for the FX-conversion rules).
Multi-source funnel attribution — Admaxxer-unique
Datafast's funnel report shows the entry-source breakdown only at step 1. You cannot ask “of the visitors who reached step 3, what was the first-touch source mix?” Admaxxer can.
Every step in an Admaxxer funnel reports its own source breakdown in addition to the absolute count. The breakdown is computed from the visitor's first-touch UTMs (sticky for the visitor's lifetime), so the source mix at step 5 is comparable to the mix at step 1 — both reference the same attribution model.
Worked example: of 200 visitors who hit /checkout in the funnel above:
- 80 came from Paid Social (first-touch
utm_source=facebookorutm_source=tiktok) - 60 came from Organic (no UTMs, referrer is Google / Bing / DuckDuckGo)
- 60 came from Direct (no UTMs, no recognized referrer)
If your funnel converts at 8% for Paid Social visitors and at 4% for Direct visitors, you have a clear answer to the question “does my funnel perform better for one channel?” That delta is invisible in a Datafast funnel and shows up directly in Admaxxer.
Combine multi-source attribution with cohort scoping for the highest-resolution analysis: scope the funnel to First-time visitors and look at per-step source mix. You'll see acquisition funnels segmented by both visitor recency and channel of origin in one report.
Time-to-conversion distribution
Beyond the median time-to-conversion in the headline, Admaxxer surfaces a four-quartile distribution: p25, p50, p75, p90. The distribution answers questions a single median can't:
- p25 — the “fast lane”: 25% of converters complete the funnel in this many minutes or less. If your p25 is 2 minutes, your fastest converters are pre-decided buyers; consider whether you can compress the funnel for the next 25% by removing friction.
- p50 — the median: half of converters take this long or less. The headline number.
- p75 — the “deliberation lane”: 75% of converters complete the funnel within this window. Use this to set the upper bound of your remarketing window.
- p90 — the “long tail”: 90% of converters complete by this many minutes. Anything beyond p90 is unusually slow — often researchers, comparison shoppers, or B2B procurement.
Why this matters for attribution: if your p90 time-to-conversion is 14 days but you're using a 1-day click-attribution window in Meta Ads Manager, ~10% of your conversions are being miscredited as Direct. The fix is to widen the attribution window in your ad platform, not change anything in Admaxxer — but the Admaxxer funnel report is what tells you the window is wrong. See /documentation/troubleshoot/attribution-discrepancies for the full attribution-window discussion.
The distribution renders as a horizontal bar chart with the four quartile markers. Hover any quartile to see the visitor-count contribution.
vs. Datafast — what Admaxxer adds
Datafast's funnel feature is a clean, well-executed implementation of the standard primitive. Admaxxer's funnel feature is the same primitive plus four layers DF doesn't expose:
| Capability | Datafast | Admaxxer |
|---|---|---|
| 2 to 5 step funnel builder | Yes | Yes |
| Page-URL, custom-goal, and revenue-event step types | Page + goal | Page + goal + revenue |
| Step-level filters (UTM, device, country) | Funnel-level only | Per-step |
| Cohort scoping (first-time / returning / paid / top-LTV) | No | Yes |
| Revenue rescued per step | No | Yes |
| Multi-source attribution at every step | Step-1 only | Every step |
| Time-to-conversion distribution (p25/p50/p75/p90) | Median only | Full quartile distribution |
| Backed by columnar OLAP scaling to 100M events | Limits not documented; observed slowdowns at high cardinality | Tinybird-backed; tested at 100M events |
| Funnel completions feed channel-contribution model | No | Yes (MMM input) |
The last row is worth expanding on: Admaxxer's MMM (Marketing Mix Model) at /dashboard/mmm consumes funnel-completion counts as one of its dependent variables. That means improvements to your funnel show up directly in your modeled channel contribution — and conversely, a funnel-completion drop is automatically attributed across paid channels in proportion to their modeled contribution. Datafast doesn't have an MMM surface to wire its funnels into.
Under the hood — how funnels are computed
Funnels are computed via Tinybird pipes that join pixel_events (the pageview and goal stream) and visitor_payments (the revenue stream). The join key is visitor_id, the first-party cookie set by the Admaxxer pixel that survives 365 days on the visitor's domain. See /documentation/data/revenue-data-flow for the full ingestion architecture upstream of the pipes.
The funnel pipe applies an ordered-event-sequence query: for each visitor, find the first pageview/goal/revenue event matching step 1, then find the first event matching step 2 with timestamp greater than step 1's timestamp, and so on. A visitor that satisfies step N but not in the right order (e.g., they hit checkout before they hit pricing) does not count toward step N's bar. This is the same ordering primitive Datafast and Plausible apply.
The funnel result for a default 7-day window typically computes in single-digit seconds for workspaces with <10M events; at the upper bound (100M events, 90-day window, 5 steps with cohort scoping) the typical compute time is ~30 seconds. Results are cached in Upstash Redis for 5 minutes, so repeated views of the same funnel hit one Tinybird query, not N.
API access
Funnels are exposed under the public API at /api/v1/analytics/funnels. The endpoint accepts the same parameters as the dashboard builder (steps, filters, cohort scope, date range), authenticates via Bearer token, and returns the same JSON shape the dashboard renders. Useful for syncing funnel results into a BI tool, a Slack digest, or a downstream cohort-analysis script.
Bearer-auth tokens are issued from /settings/api-keys; rate limits and quota rules are documented in the developer reference.
Setup tutorial — building a Marketing Acquisition Funnel
A worked end-to-end tutorial. We'll build the SaaS funnel Land → View Pricing → Click Trial → Activate Trial → First Revenue from scratch, in five steps.
- Define each step. Open /dashboard/analytics › Funnels › + New Funnel. Name the funnel “Marketing Acquisition Funnel.” Add five steps:
- Step 1: Page URL, matcher
/(root) — or any landing-page pattern that represents your acquisition entry. - Step 2: Page URL, matcher
/pricing. - Step 3: Custom goal, matcher
start_trial_clicked(a goal you fire on the “Start Free Trial” button click viatrack('start_trial_clicked')). - Step 4: Custom goal, matcher
__admx_signup(Admaxxer's auto-tracked signup goal — fires when an account is created). - Step 5: Revenue event, matcher
any revenue event.
- Step 1: Page URL, matcher
- Add filters. Set the date range to “Last 30 days.” Optionally add per-step UTM filters — e.g., scope step 1 to
utm_medium=paidif you only care about paid acquisition. Skip filters entirely on a first pass; you can add them after the baseline funnel computes. - Pick cohort scope. Default is All visitors. Switch to First-time visitors only for a clean acquisition funnel, or to Came from Meta ads if you're optimizing a single paid channel. The cohort scope dramatically changes the report; expect to run the same funnel under multiple cohorts side by side.
- Save and share with team. Click Save. The funnel computes asynchronously; first results land in single-digit seconds. The funnel becomes visible to all workspace members — owners and members with the
analytics:writescope can edit it; viewers see the saved version. - Read insights and iterate. Look at three things in this order:
- The largest drop-off transition — that's your highest-leverage optimization target.
- The revenue-rescued column on that transition — that's the dollar-value of fixing it.
- The source breakdown at the dropping step — if one channel converts dramatically worse, that channel is your secondary optimization target (you may need a channel-specific landing-page variant).
Iterate weekly. A funnel that's read once doesn't move conversion; a funnel that's read every Monday morning and acted on does. Pin the funnel to your dashboard for one-glance visibility on the next visit.
Limits and gotchas
- Maximum 5 steps. The UI caps funnel definitions at 5 steps to keep the report readable. Funnels longer than 5 steps tend to render unintelligibly on a single screen; for longer journeys, build two overlapping funnels (steps 1-5 and steps 4-8) and compare the overlapping middle.
- Step ordering matters. The funnel computes “first time the visitor hit step N after hitting step N−1.” A visitor who hits checkout before pricing does not count toward the pricing → checkout transition. This is the same semantic Datafast and Plausible apply — it's not a bug, it's a deliberate ordering primitive.
- Anonymous → identified user transition. A visitor can start as anonymous and become identified mid-session (for instance, they sign up between step 3 and step 4). Admaxxer funnels use
visitor_idcontinuity for ordering, so the transition doesn't break the funnel. The visitor's pre-signup events and post-signup events both belong to the samevisitor_id, and the funnel sees a single unified journey. - Cross-device journeys. By default,
visitor_idis per-browser-per-device. A visitor who lands on mobile and converts on desktop is two visitor IDs — the funnel will see two separate, incomplete journeys. To stitch cross-device journeys, fireidentify(user_id)on each device after login; Admaxxer's pixel will merge the pre-identify visitor history into the post-identify user record. - Path normalization. URL patterns are matched after path normalization (trailing-slash stripping, query-string stripping, hash stripping). If you wrote
/checkout/in your matcher, it will silently match/checkoutand/checkout?ref=emailtoo. This is almost always what you want; if it isn't, see /documentation/troubleshoot/sales-mismatch for path-normalization troubleshooting. - Goal naming collisions. A merchant-defined goal cannot use the
__admx_prefix — that namespace is reserved for Admaxxer's auto-tracked goals (__admx_signup,__admx_add_to_cart,__admx_email_capture,__admx_checkout_completed). The funnel builder will reject a step matching__admx_*if you typed it manually but didn't pick it from the auto-list. - Window inclusivity. The funnel date window is inclusive on both ends and uses the workspace's reporting timezone. A visitor whose first-step event is at 23:59 on the last day of the window still counts; a visitor whose first-step event is at 00:00 on the day after still does not. Edge-of-window funnels are sensitive to timezone — verify your workspace timezone in /settings if your funnel counts disagree with another tool.
When the funnel report looks wrong
Three common patterns and their fixes:
- Step 1 count is dramatically lower than expected. Almost always a path-normalization mismatch. Check the matcher pattern at step 1 against the actual URL the pixel records. Use the dashboard's Pages card (powered by
p_top_pages) to see the normalized path values for the pages you expected to match. See /documentation/troubleshoot/sales-mismatch for the path-mismatch debug walkthrough. - Drop-off seems impossibly steep on one transition. Often a cohort or filter mismatch — you have a UTM filter on step N but not step N−1, so step N is filtering visitors that step N−1 admitted. Re-check the filters; in 90% of cases, you want filters at the funnel level (not the step level) for consistent denominators.
- Conversion rate disagrees with your ad platform's reported conversion rate. The disagreement is usually attribution-window related — your ad platform attributes on a 1-day click model, while Admaxxer attributes on a session-cookie model with 365-day persistence. The Admaxxer number is closer to ground truth for first-touch attribution; the ad platform's number is closer to ground truth for last-click attribution. See /documentation/troubleshoot/attribution-discrepancies for the full reconciliation walkthrough.
Related documentation
Custom goals · Dashboard analytics cards · Revenue data flow · Attribution discrepancies · Sales mismatch troubleshooting · UTM best practices