A read-only analysis of one sales funnel, done by Claude Code with the ef CLI (command-line tool): sales by funnel, the funnel's step table, the upsell take rate per buyer from orders, a traced session that confirms the finding, a split test call made knowingly, and a developer brief ranked by money. The clips replay that analysis on the fictional Northwind Supplements brand. Every number in them is invented; the commands and the output format are the CLI's own.
Why this works: the full worked analysis, including the two claims the agent had to take back, is in Claude Code funnel analysis. To let Claude Code edit pages instead, see add an MCP server to Claude Code.
You need Claude Code, installed and signed in, Node.js 18 or newer, and the CLI: npm i -g @elasticfunnels/cli. In a new, empty folder, ef init signs you in through the browser, binds the folder to one brand and installs the skills. A folder you bound before only needs ef update, then step 1.
mkdir northwind && cd northwind ef init
1Install the skills and set the timezone
In the bound folder, run ef claude. It updates the folder's CLAUDE.md and installs five skills into .claude/skills/: ef-stats, ef-funnel-analysis, ef-upsell-diagnosis, ef-funnel-performance and ef-page-events. Claude Code loads one when a question matches it, so you never name them.

Then tell the CLI which timezone your brand counts days in: ef config set analyticsTz America/New_York. Run ef stats --range 7d to check: the first line names the range and the zone.
Pitfall: without analyticsTz the CLI counts days in your computer's timezone, which is not always your market's. Every day boundary shifts, so a "drop" on one day can be the edge of the range moving.
2Ask for sales by funnel
Start claude in the folder and type: show me sales by funnel for the last 30 days. Claude Code runs ef stats by funnel_id with sales, revenue, sessions, conversion rate and AOV (average order value).

Look for three things in the answer: the range and timezone stated, a funnel whose conversion rate is too good to be real (38.51% here, most likely buyers who reach checkout without a tracked page view: compare that funnel on sales and revenue, and confirm with a trace as in step 5), and the (unlabeled) row, orders with no funnel attached. The funnel with the traffic is the Main VSL (video sales letter) funnel: 4,210 sessions at 2.76%.
Pitfall: --limit cuts the table and says so (4 of 8 rows). Before anyone concludes "most of our sales are X", check the row count.
3Build the funnel's step table
Pick the funnel with the traffic and name the problem: walk me through the Main VSL funnel, the upsell take is low. The ef-funnel-analysis skill joins three sources into one table: ef funnels product-flow 12 (which page follows which purchase), ef stats by page --funnel 12 (sessions and sales per page) and ef products list (prices).

Read it in buyer order: front end, upsell 1, downsell, upsell 2, upsell 3. Here the half-price downsell converts about 2.6 times the upsell (12.1% vs 4.6%): buyers want more, and the price is the objection. Upsell 3 took 1 sale from 49 sessions.
Pitfall: session counts on pages after checkout are unreliable (reloads and repeat visits add some, missed page views drop others), so sales per session can misstate the take per buyer. The ranking between steps holds; the rates do not. Step 4 measures buyers.
4Check upsell take per buyer from orders
Before you change an upsell, ask who takes it: before we change upsell 1: who actually takes it? check orders, not sessions. Claude Code runs ef orders buyers --funnel 12 --range 30d: every buyer's first package, what they paid, and whether they bought anything after it. Order bumps are left out, and no customer data is printed.

The table settles what the step table can't. Buyers of the biggest package at full price took "more of the same" best (9 of 39, 23.1%), 1-bottle buyers took nothing, and the sale buyers, who paid $94 for 6 bottles, took nothing at all.
Pitfall: don't let the agent guess what a segment wants. In the real analysis behind this tutorial, Claude Code first suggested a different product for 6-bottle buyers; the orders showed they were the best takers of the same one, and it retracted. Samples are small, so ask for the n next to every rate.
5Trace a session to confirm the finding
A table says what happened, a session trace says why. Ask: why did none of the sale buyers take an upsell? trace a few. Claude Code takes session ids from ef orders list --funnel 12 --page 4471 --json and runs ef sessions show <id> on each: landing page, referrer, affiliate, and the path the buyer took.

All three traces read /summer-sale → checkout → /members-area. Those buyers never see an upsell, so it's routing, not a weak offer. If the house-list sale is meant to skip upsells, fine; if not, they need a price-matched upsell, not the $228 one.
Pitfall: the compiled funnel flow can show a path the runtime never takes (a page that sits in two page groups, for example). Confirm a routing claim with orders and two or three traces before anyone rewires the funnel. When a trace shows a buy click with no page view before it, ef sessions show flags a TRACKING GAP: that page's conversion rate is understated.
6Read the split test result before you act
If a step has a test running, ask whether it can finish: is the upsell 1 split test ever going to finish? Claude Code runs ef stats split 318 from the day the test started and reports the p-value and the sample size the app computed. It never runs its own test.

Here the challenger is ahead (7.53% vs 4.04% for the control), but there is no winner: the p-value is 0.2980 and each arm needs about 700 sessions. With about 50 sessions a month per arm, that is roughly another year. The honest label is "trending, not conclusive".
Pitfall: a low p-value on a small sample is what peeking too early looks like. Decide the sample size before launch, judge at that size, and when traffic can never get there, say so and make the call as a business decision.
7Declare the winner, if you decide to
The call is yours, not the agent's. Say it plainly: call it for Short copy, I accept that it's a manual call. Claude Code runs ef splits variants 318 to match names to node codes, then ef splits winner 318 "Short copy" --yes.

The command first prints the p-value and the sample still needed, warns that this is a manual call, then finalizes the test and sends all its traffic to the winner. Claude Code then records the decision, both arms' numbers, the range and the timezone in elasticfunnels/split-tests.md.
Pitfall: don't let the agent call a test early on its own. ef stats can't change anything, and a winner is only declared when you ask for it. --yes is needed because Claude Code is not an interactive terminal.
8Have it write a developer brief
End with something a person can act on: write this up for a developer: ranked by money, with links and sample sessions. Claude Code writes a Markdown file in the project (research/main-vsl-dev-brief.md here) with an issue table, then per issue: the evidence, dashboard links, sample session and order ids, what to check, how to tell it's fixed, and the commands that reproduce the numbers.

Read it before you send it. Each issue should point back to a number you saw in an earlier step; anything the agent inferred rather than measured should say so.
Pitfall: a brief without its range and timezone can't be reproduced. The developer should get the same numbers from the same commands.
Common Claude Code analysis mistakes
- Reading "unavailable" as zero. Metrics differ per brand. When one is missing, the CLI says
Not available for this brand: report that as "not tracked", never as 0. - Skipping the timezone. Set
analyticsTzonce, and have every answer state its range and zone. Two people comparing numbers from different zones will both be right and still disagree. - Calling the comparison year over year. The VS column is the period right before, of the same length. A 30-day range compares with the 30 days before it.
- Concluding from a cut table.
--limittruncates and printsN of M rows. Read the row count before you sum or rank. - Mixing sessions and buyers. Upsell sessions include reloads and repeat visits and miss some buyers. Take per buyer comes from
ef orders buyers, not from sales per session. - Flagging a checkout page as "not wired". Checkout pages are not steps in the funnel graph: the checkout is picked when the buyer clicks the buy link, from the domain's active merchant, unless a page event overrides it.
- Calling a split test early. Read the significance result the app computed. A trend with no winner is "trending, not conclusive"; ending it is a business decision you make and record, not a statistical result.
Keep going
The full worked analysis, with the agent's corrections: Claude Code funnel analysis. Building and split-testing pages with an agent instead: Claude Code for marketing. Page edits from Claude Code: add an MCP server to Claude Code. Everything the CLI does: the ef CLI. Test the upsell change you decide on: post-purchase upsell and downsell. All tutorials: the Academy.