Turning content into pipeline
Most content programmes are measured on traffic because traffic is the number that is easy to get. This is how to measure content on the thing you actually want — whether it brings people who buy — and what to do with the answer.
Time to build: an afternoon. Time to be confident: a quarter, because content is slow and you need enough conversions to compare.
Why traffic is the wrong number, concretely
Two pages. One brings 8,000 visitors a month and 1% of them become high intent. One brings 400 and 22% do. The first page wins every dashboard and the second page is your business. Ranked by traffic you will write more of the first.
The number that separates them is already in one call.
Step 1 — Establish what you can and cannot see
Before any analysis, read the coverage:
a = get("/attribution", days=90)
print(a["totals"]["touch_coverage_pct"], a["totals"]["identify_rate"])
touch_coverage_pct is the share of visitors whose first touch is visible. If
it is 30%, every statement below describes that 30%. That is fine for
comparing pages against each other — the bias is broadly similar across them —
and it is not fine for reporting totals to anyone.
Write the number at the top of whatever you produce. A content report that does not state its coverage is the kind of artefact that gets quoted for two years.
Step 2 — Rank pages by yield, not volume
rows = [
{
**p,
"yield": p["high_intent"] / p["visitors"] if p["visitors"] else 0,
}
for p in a["landing_pages"]
if p["visitors"] >= 200 # below this, yield is noise
]
by_yield = sorted(rows, key=lambda r: r["yield"], reverse=True)
by_volume = sorted(rows, key=lambda r: r["visitors"], reverse=True)
Print both lists side by side. The interesting pages are the ones that move several places between them — high volume and low yield is where your budget is going; low volume and high yield is where it should go.
Step 3 — Ask what the winners have in common
Here are our landing pages, ranked by the share of their visitors who reach
high intent:
{by_yield_json}
And ranked by raw traffic:
{by_volume_json}
Coverage is {touch_coverage_pct}% — say what that means for confidence before
anything else.
Then: what do the top-yield pages have in common that the high-volume,
low-yield pages do not? Ground every claim in the URLs and numbers here. If the
only honest answer is "the top pages are all about one product area", say that
rather than constructing a content theory.
That last instruction stops the most common failure: a model producing a plausible essay about "buyer intent content" from five URLs.
Step 4 — Follow one page all the way through
Aggregate yield tells you where to look. To decide what to write, take a single high-yield page and ask what happened after it:
ask("Which pages do people read after /guides/migration, and which of those "
"paths end in a purchase?")
The answer is a path, and a path tells you what to write next: the page people go looking for and do not find.
Step 5 — Decide, and write the decision down
Three decisions come out of this, and only three:
- Write more like this. Name the page and the yield that justified it.
- Fix this. High volume, low yield, and a clear reason — usually a page that ranks for a query your product does not serve.
- Stop. Low volume, low yield, costing maintenance.
Write down the number that justified each decision, with the date and the coverage. In six months someone will ask why you stopped writing about X, and "we decided in September" is not an answer.
Step 6 — Re-measure, honestly
before = get("/attribution", days=90) # run before the change
# ... ship the content change, wait a full quarter ...
after = get("/attribution", days=90)
Two traps here, and both are common enough to have bitten this product's own analysis:
A level is not a change. Yield rising after you shipped does not mean shipping caused it. If you want a causal claim, you need a dated intervention and a proper test — ask the assistant "the new guides went live on 2026-05-01, did that move high-intent yield?" and it will run an interrupted time series and give you an interval. An interval containing zero means you do not have an effect, and it will tell you so rather than describing the midpoint as a small win.
Coverage moved too. If touch_coverage_pct changed between the two
windows, some of your "improvement" is measurement. Compare coverage first,
every time.
What will go wrong
Seasonality eats a quarter. Content yield in December is not content yield in March. Compare with the same quarter last year if you have it, and say so if you do not.
A page ranks for the wrong query. The highest-traffic, lowest-yield page is very often ranking for a term adjacent to your product. That is not a content quality problem and rewriting it will not help.
The rollup is nightly. computed_at tells you how fresh the data is.
Shipping in the morning and checking at lunchtime tells you nothing.
Next: find the pages that create pipeline · why attribution covers less than you think
Markdown source: /developers/playbooks/turning-content-into-pipeline.md