Added Gift source attribution for gift-link signups#28896
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
| Command | Status | Duration | Result |
|---|---|---|---|
nx run ghost:test:ci:integration |
✅ Succeeded | 2m 41s | View ↗ |
nx run ghost:test:integration |
✅ Succeeded | 2m 18s | View ↗ |
nx run ghost:test:legacy |
✅ Succeeded | 2m 52s | View ↗ |
nx run ghost:test:e2e |
✅ Succeeded | 2m 7s | View ↗ |
nx run-many --target=build --projects=tag:publi... |
✅ Succeeded | 3s | View ↗ |
nx run @tryghost/admin:build |
✅ Succeeded | 5s | View ↗ |
nx run-many -t test:unit -p ghost |
✅ Succeeded | 2s | View ↗ |
nx run ghost:build:assets |
✅ Succeeded | 2s | View ↗ |
Additional runs (2) |
✅ Succeeded | ... | View ↗ |
💡 Verify your cache is correct by running tasks in a sandbox. Read docs ↗
☁️ Nx Cloud last updated this comment at 2026-06-25 12:32:22 UTC
e551dc1 to
101169f
Compare
no ref
- gift-link visits (`{post_url}?gift={token}`) unlock a single gated post; when
the reader signs up they're attributed to whatever channel the link was shared
through (usually Direct), so gift-derived signups are invisible as a distinct
source in the Growth tab
- gift links leave no server-side trace tying a signup to the gift (unlike gift
subscriptions, which set member.status='gift'): the gift-links service only
validates tokens and the `_gift` token is surfaced to Tinybird for visit
analytics only - so at signup the gift signal exists solely as the `?gift`
param on the unlocked post's URL in the browser
- the history recorder ignores that param (it only reads ref/source/utm), so tag
a `?gift` visit with referrer source 'Gift' (medium 'gift') there; it then
flows through the normal referrer pipeline into
members_created_events.referrer_source. The real referrer url is kept and an
explicit ref/source/utm on the link still wins
- a valid token renders in place (invalid tokens are 301-stripped pre-render),
so a `?gift` present when the recorder runs is always a genuine gift view
101169f to
bd86772
Compare

no ref
Problem
Gift-link signups (
{post_url}?gift={token}) don't show up as a distinct source in the Growth tab. When a reader of a gift-unlocked post signs up, they get attributed to whatever channel the link happened to be shared through — usually Direct when shared privately — so there's no way to see how many members a site gains via gift links.Unlike gift subscriptions (a gifted paid subscription, which set
member.status = 'gift'), gift links leave no server-side trace tying a signup to the gift: the gift-links service only validates tokens (no redemption — the redemption columns were dropped in 6.48), and the_gifttoken is surfaced to Tinybird for visit analytics only. So at signup the gift signal exists solely as the?giftparam on the unlocked post's URL in the browser — and the history recorder ignores it (it only readsref/source/utm/attribution_id).Change
Tag a validated
?giftvisit with referrer sourceGift(mediumgift) in the frontend history recorder, so it flows through the existing referrer pipeline intomembers_created_events.referrer_sourceand shows up in the Growth sources breakdown. No new plumbing — it rides the same path every other channel (newsletter, Twitter, Ghost Explore) already uses.ref/source/utm_sourceon the link still wins, so a site owner's own tagging isn't clobbered.Gift.301-stripped before render — so a?giftparam present when the recorder runs is always a genuine gift view.Logic lives in a small, unit-tested helper (
getGiftReferrer) inurl-attribution.js; the IIFE inmember-attribution.jsjust applies it.Open for discussion 🧵
Opening as a draft to agree the details before polishing:
ref/source/utm_sourceon the link wins overGift. ShouldGiftinstead always win, on the basis that the gift is the more meaningful acquisition signal?Giftis stored as a free-text source, so it shows in Growth but without first-class grouping/icon. Worth adding a canonical entry in@tryghost/referrer-parser'sreferrers.json?Tests
getGiftReferrerunit tests inurl-attribution.test.js: gift link, no gift, defers to explicitref, defers to explicitutm_source, malformed URL.