AIRANKS — The Authoritative Rankings for AI Web Content

AIRANKS measures AI visibility: we ask AI models real product and service questions, capture the complete answers as immutable observations, and publish what they contain — which brands were mentioned, which domains were cited, and which exact pages were linked. Every domain gets an AIR score from 1–10 (a decile of visibility in the active dataset; 0 means insufficient data), with the methodology in the open.

AIR

BLOG

Skip to main content

the ledger notes

The pipeline we didn't need

Build LogAugust 28, 2026 by Jeremy Schoemaker

The ask was simple enough: make the report PDF look amazing, and let an agency put their own logo on top and their own contact details along the bottom.

I convened the council. Six models, one chair, and a rule that a theory is never the answer until it is reproducible. Five seats came back reachable. All five opened saying roughly the same thing: the browser's Save-as-PDF is not a product, move to server-side Chrome, add a branding table.

Unanimity among five models is not evidence. It's five copies of one assumption. So before running round two, I went and measured.

The first thing I measured was the font

The document declares --font-display: 'Instrument Sans'. I wanted to know whether that font actually arrives on a customer's machine. The obvious probe is document.fonts.check(), and it returned true, and it was lying — that API returns true when a fallback is available, which is almost always.

So I measured glyph widths instead. Same string, 40px, rendered in each candidate:

tested width "Instrument Sans" alone 688.11 system default 688.11 Helvetica 758.23 the document's actual body chain 758.23

Instrument Sans resolves to exactly the system default, which means it isn't installed. The document's own chain resolves to exactly Helvetica. Mono resolves to Menlo. document.fonts.size is zero — there are no @font-face rules at all.

The brand typography isn't degraded on customer machines. It's absent, everywhere, including ours. We never saw it because we'd been reading a document that looked fine in Helvetica.

The second thing I measured killed the council's argument

The strongest case for a server-side pipeline was that browser printing drops our background colours — and it does. Chrome's print dialog has "Background graphics" off by default. I rendered it both ways: with backgrounds, the green AIR mark and cream plates; without, a grey ghost and white boxes. The brand simply leaves.

Then I looked at why, and found this inside a @media print block:

.deboss-print .deboss-content{ ... print-color-adjust: exact; }

print-color-adjust: exact is the property that tells a browser to print backgrounds anyway. It was applied to .deboss-content — an element which has no background. The fills live on the parent, .deboss-print, and on .air-mark. Neither got the property.

The property was on the wrong element. I injected it onto the right ones, re-rendered with backgrounds still off, and the green came back.

An entire architectural argument, resting on a one-line CSS bug.

The third thing overturned a comment in our own code

scripts/build-document-pdf.mjs — a working PDF pipeline already in this repo — carries this in its docblock:

Chrome implements no CSS paged-media margin boxes, so a stylesheet cannot draw a folio [...] Page.printToPDF's headerTemplate / footerTemplate is the only route to "3 / 5" in our own type.

Seraph, the council's verifier, refused to sign the round-one ruling until somebody re-tested that claim against the actual pinned Chrome. It was right to refuse.

I wrote three forced pages with @bottom-center { content: "FOLIO " counter(page) " of " counter(pages) }, rendered with displayHeaderFooter: false so that only CSS could possibly draw it, and ran pdftotext:

RUNNING HEAD TEST / Page one / FOLIO 1 of 3 RUNNING HEAD TEST / Page two / FOLIO 2 of 3 RUNNING HEAD TEST / Page three / FOLIO 3 of 3

Chrome 151. Pure CSS. The comment was true when it was written and stopped being true in Chrome 131, November 2024. We'd been reasoning from a note we wrote ourselves and never re-checked.

Seventeen retractions

Round two put all of that in front of the seats. Every reachable member retracted the margin-box claim, each citing the experiment. Mouse retracted its entire opening position:

was: Ship server-side CDP as the real deliverable; window.print is not a product. now: First slice is CSS finishing. CDP is a delivery track sequenced after, only if we need a file.

Seraph retracted the ground it had stood on while keeping the conclusion:

was: Adopt CDP because it is the only route that embeds fonts and produces a true folio. now: Adopt CDP on delivery and determinism grounds only; both capability claims I cited are falsified.

Seventeen retractions across five members. That is the number I care most about in a council. A round with zero retractions means nobody read anybody.

Where that leaves the pipeline

Every capability argument died:

  • backgrounds → a CSS bug
  • folio → works in CSS since Chrome 131
  • font embedding → base64 @font-face, +92 KB, no browser needed
  • cross-browser determinism → I measured Chromium, Firefox and WebKit at a 0.77% spread, with cover height identical to the pixel. And the largest source of variance was the font bug — three engines picking three different fallbacks. Fix the fonts and they converge.
  • "too slow to be synchronous" → rasterization is 104 ms, byte-identical across five runs

One argument survived, and it's the honest one: you cannot email a PDF that only exists when a user clicks Print. Server-side rendering is a delivery capability, not a quality one.

So: amazing is a CSS problem. CDP is a delivery problem. Sequence them separately.

The constraint that actually bit the feature

Tank found the thing I'd missed. The spec wants the agency's logo linked to their site, throughout the report. CSS margin boxes hold generated content — not DOM. A margin box cannot contain a hyperlink.

So I tested three mechanisms and counted link annotations per page inside the resulting PDF:

mechanism every page? clickable? @page margin box yes no — generated content position: fixed anchor no — rendered pages 1–2, silently dropped page 3 partly display: table-header-group yes, 4/4 yes — 52 link annotations

position: fixed is the intuitive answer and it fails silently on the last page, which is the worst way for anything to fail. The winner is the oldest trick in the CSS 2.1 spec: a <thead> set to table-header-group repeats on every page by mandate, and it can hold a real anchor wrapping a real image.

Verified output: customer logo in the header on page one and page three; company name, address, phone, clickable mailto: and clickable site link along the bottom of every page; and the CSS folio running at the same time.

The whole white-label header/footer requirement, with no new infrastructure.

The part that wasn't a technology question

Every member opened insisting AIR's branding must be unstrippable. An Operator went and looked at what the industry actually does: Ahrefs, Semrush, SE Ranking, AgencyAnalytics, Databox, Moz, Whatagraph — every one of them lets an agency remove the vendor's branding completely. No legal requirement, no known litigation.

So I made them split a distinction they'd been eliding:

  • Vendor marketing attribution — our logo, "generated by AIRanks.net." Removable. That's a business decision, not an ethical floor.
  • Measurement provenance — the CHECKED: and EVIDENCE: chips, the confidence intervals, the sample sizes, "What this report cannot tell you." Not attribution at all. It's the calibration of the claims. Strip it and the numbers quietly start meaning something other than what they say.

All five retracted the conflation. The industry even has the pattern already: a "Data Sources" line, present in about 94% of white-labelled reports. Agency's brand on top, agency's contact block at the bottom, and a neutral "Measured by AIRanks.net" line inside the locked provenance block.

Two things I got wrong along the way

An early PDF render came back with a black page and looked like total failure. It was an alpha channel in my own conversion, rendered as black. I nearly wrote it up. Re-composited on white and the page was fine.

Later, my first header test showed no logo, which would have implicated the mechanism. The mechanism was fine — my test PNG was a corrupt data stream. I regenerated it and re-ran rather than leaving the gap and calling it verified.

Both are worth recording, because a chair that reports its own clean runs and quietly drops its messy ones is running a poll, not a council.

What's still open

Two things, and I'm not going to pretend either is settled.

Snapshot the branding onto each report, or resolve it live? Three members want an immutable snapshot. Tank dissented. I ruled for Tank on evidence: there are zero stored PDF artifacts today, so a snapshot column would be a column with no reader — a failure mode this codebase has already been bitten by. Revisit the day a stored artifact exists.

A4 or Letter? The report currently ships A4. The other pipeline in the same repo ships Letter. Two documents, two paper sizes, one company. I can measure the MediaBox; I can't measure which one our customers want. That one's not mine to call.

Synchronous or queued rendering? Morpheus withheld its signature pending a real concurrency and memory test. It's right, and I have to concede the gap: I measured 104 ms of rasterization, but my memory sample was polluted by a second browser running on the same machine, so I have no clean number and I'm not going to quote a dirty one.

The best thing a council produces isn't the verdict. It's the list of things nobody was allowed to assert without a test.

← Back to blog