Skip to content

Sell the rectangle instead of the sponsored line - #2

Merged
ralyodio merged 1 commit into
masterfrom
feat/ad-rectangle
Aug 29, 2026
Merged

Sell the rectangle instead of the sponsored line#2
ralyodio merged 1 commit into
masterfrom
feat/ad-rectangle

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Switches the ad from the inline text link to the 300×250 rectangle.

The text link was chosen because it is the only format that fills its container, and so the only one safe in a column whose width nothing here can measure without a script. That reasoning holds — it is also the smallest thing the slot can sell. The rectangle is the inventory worth having, so the column gets made to fit it instead.

One size, everywhere

banner_300x250. 300px is the widest fixed creative that still fits a 320px phone, which is what makes a single size viable at all:

  • picking a size by viewport would need a script, and the whole embed exists to avoid running one;
  • rendering two units so CSS can hide one bills two impressions for one reader — serving meters server-side at fill time, whether or not anyone saw it.

The columns that were too narrow

Every creative is laid out at its format's exact pixel width inside the frame, so a narrow column crops it rather than reflowing it. Measured before the fix:

Viewport Column Result
320px, test page 250px cropped 50px — a fifth of the ad
360px, test page 290px cropped 10px
390px+ ≥300px fine

Below 640px the unit now escapes its column's padding and centres against the viewport (margin-inline: calc(50% - 50vw)). The ad does not get bigger; it stops being cropped by a gutter. body already hides horizontal overflow, so a stray pixel cannot start a sideways scroll.

Re-measured at 320 / 360 / 390 / 430 / 768 / 1280 on both pages: creative is 300px everywhere, cropped nowhere, and scrollWidth === clientWidth at every width including either side of the 640px breakpoint.

Theme

Still nothing asks for one, and that is now deliberate rather than a gap. Since profullstack/crawlproof.com#221, /api/ads/frame ships both palettes behind prefers-color-scheme and the frame answers it from the reader's own browser — a better signal than this end could offer, given the site's theme is a stored preference the server never sees.

Verified on the same page: rgb(7,10,16) for a reader in dark, rgb(246,249,251) for one in light. The dark bar on the light theme is gone.

Tests

The test pinning format=text_link pinned the reasoning this PR reverses, so it is replaced rather than deleted — the new one holds the format to a single fixed size and the frame to that format's exact box, which is the property that breaks if either drifts. A second new test holds the embed to naming no theme, so nobody re-adds a guess that would override the reader's browser.

Verified

biome check clean · 66 tests pass · static export still ad-free (desktop app untouched) · all 24 pages pass the browser smoke test · no CSP violations and no page errors in a real browser at desktop and mobile widths in both themes.

The unit was a text link, on the reasoning that it is the only format that
fills its container and so the only one safe in a column whose width nothing
here can measure. That is true, and it is also the smallest thing the slot can
sell. The rectangle is the inventory worth having; the column just has to be
made to fit it.

So the default format is `banner_300x250`. 300px is the widest fixed creative
that still fits a 320px phone, which is what makes one size for every viewport
possible at all — picking by width would need a script, and rendering two units
for CSS to hide one would bill two impressions for a single reader.

Two columns on this site are narrower than 300px, and every creative is laid
out at its format's exact pixel width inside the frame, so a narrow column
crops it rather than reflowing it: a test page at 320px gave the unit 250px and
cut a fifth off the ad, and 360px cut 10px. Below 640px the unit now escapes
its column's padding and centres against the viewport instead. The ad does not
get bigger — it just stops being cropped by a gutter. Measured at 320, 360,
390, 430, 768 and 1280: the creative is 300px everywhere and the document never
scrolls sideways.

Nothing asks for a theme, and that is now deliberate rather than a gap.
`/api/ads/frame` ships both palettes behind `prefers-color-scheme`, which the
frame answers from the reader's own browser — a better signal than this end
could offer, since the site's theme is a stored preference the server never
sees. The unit renders on #070a10 for a reader in dark and #f6f9fb for one in
light, on the same page.

The test pinning `format=text_link` pinned the reasoning above, so it is
replaced rather than deleted: the new one holds the format to a single fixed
size and the frame to that format's exact box, which is the property that
breaks if either drifts. A second test holds the embed to naming no theme.
@ralyodio
ralyodio merged commit fc505df into master Aug 29, 2026
4 checks passed
@ralyodio
ralyodio deleted the feat/ad-rectangle branch August 29, 2026 06:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant