Skip to content

Tag strips lose their bullets, and a parts link can be an affiliate link without a code change - #10

Merged
ralyodio merged 1 commit into
mainfrom
worktree-parts-affiliates
Sep 6, 2026
Merged

Tag strips lose their bullets, and a parts link can be an affiliate link without a code change#10
ralyodio merged 1 commit into
mainfrom
worktree-parts-affiliates

Conversation

@ralyodio

@ralyodio ralyodio commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

The bullets

The parts vendors rendered as a bulleted, indented list. The site's own Tags component writes <span class="tags"> with <a class="tag"> children; I wrote <ul class="tags"> with <li class="tag">. .tags had no list-style or padding reset, so the browser's discs and its 40px indent came through — the same component looking like two different things depending on which markup someone reached for, which is the same failure mode as the type-less input last time.

Fixed in both places: .tags now clears the marker and the indent so either spelling renders identically, and the parts entries use the house pattern where the tag is the link, rather than a pill with a differently-coloured link inside it.

Affiliate links

Groundwork, not an account — see the note at the bottom on why.

Every one of these networks builds a tracking link the same way: their own URL with the real destination encoded inside it. Rather than teach this file the shape of a CJ, Rakuten and EPN link and get one of them subtly wrong, a deployment supplies the template its network gave it:

AFFILIATE_LINKS="ebay=https://rover.ebay.com/rover/1/711-53200-19255-0/1?mpre={url}&campid=5338XXXXXX,
                 napa=https://click.linksynergy.com/deeplink?id=ID&mid=MID&murl={url}"

and the destination is encoded into the hole. So a new network needs no code, only its template.

  • A vendor with no template is linked plainly — which is all six of them today.
  • A template with no {url} is ignored, rather than sending every buyer to a vendor's front page and tracking nothing.
  • A non-https template is ignored.
  • Junk between the commas doesn't take the rest of the list down with it.
  • A wrapped link is marked sponsored: true in the JSON payload and carries rel="sponsored nofollow noopener", which Google and the FTC both want. Unwrapped links stay rel="nofollow noopener".
  • The page shows a disclosure line only when a link on it actually pays us.

Which programmes actually exist

Checked against the vendors and networks rather than taken from an affiliate directory, and recorded next to each vendor in PARTS_VENDORS so nobody re-researches it:

Vendor Programme
eBay Motors eBay Partner Network
AutoZone CJ Affiliate
NAPA Rakuten Advertising, 1% baseline, 30-day cookie
RockAuto none on any major network
O'Reilly Auto Parts none found
Car-Part.com none found

What is not in this PR

No account was created and no application was submitted. All three programmes gate on a publisher account with the network plus a W-9 carrying an SSN or EIN and payout details, then human approval. That is a binding agreement in Anthony's name and his tax identity to supply — the same wall ~/affiliate-signup-pack.md documented in August ("Registering means creating an account and accepting a binding agreement as you… That is yours to sign").

The blocker is not automation, so a sh1pt browser recipe would not clear it. The moment any one of them is approved, it is one env var and no deploy-time code change.

Verified

  • 118 tests pass (4 new, covering plain-by-default, wrapping + sponsored, the three rejected template shapes, and an unknown vendor)
  • biome clean
  • Rendered in Chrome with a test template set: ul.tags computes list-style: none, padding-left: 0px, margin-left: 0px; the eBay pill points at rover.ebay.com with rel="sponsored nofollow noopener" while the other five stay on their own hosts with rel="nofollow noopener"; the disclosure line appears

🤖 Generated with Claude Code

https://claude.ai/code/session_012BzJdwiBGU9hmMGE5fBxjA

…ink without a code change

The parts vendors rendered as a bulleted, indented list because the strip was
written `<ul class="tags">` while the site's own Tags component writes
`<span class="tags">` with `<a class="tag">` children. The class had no
list-style, so the same component looked like two different things depending on
which markup somebody reached for. It now clears the marker and the indent, so
either spelling renders the same, and the parts entries use the house pattern
where the tag IS the link rather than a pill with a link inside it.

The affiliate half is groundwork, not an account. Every one of these networks
builds a tracking link the same way: their own URL with the real destination
encoded inside it. So rather than teach this file the shape of a CJ, Rakuten or
eBay Partner Network link and get one subtly wrong, a deployment supplies the
template its network gave it:

  AFFILIATE_LINKS="ebay=https://rover.ebay.com/rover/1/711-...?mpre={url}&campid=..."

and the destination goes in the hole. A vendor with no template is linked
plainly, which is all six of them today. A template with no `{url}`, or one that
is not https, is ignored rather than sending every buyer to a vendor's front
page.

A wrapped link is marked `sponsored` in the payload and carries
rel="sponsored nofollow", which Google and the FTC both want, and the page shows
a disclosure line only when a link on it actually pays us.

What each vendor's programme is, checked rather than taken from an affiliate
directory, is recorded next to the vendor: eBay through Partner Network,
AutoZone through CJ, NAPA through Rakuten at 1% and a 30-day cookie. RockAuto,
O'Reilly and Car-Part.com run no public programme, so nobody needs to go looking
for a link id that has never existed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012BzJdwiBGU9hmMGE5fBxjA
@ralyodio
ralyodio merged commit 04c8c89 into main Sep 6, 2026
3 checks passed
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