Skip to content

Pass gift through the page hit pipeline#742

Open
jonatansberg wants to merge 1 commit into
mainfrom
ber-3728-gift-id-passthrough
Open

Pass gift through the page hit pipeline#742
jonatansberg wants to merge 1 commit into
mainfrom
ber-3728-gift-id-passthrough

Conversation

@jonatansberg

@jonatansberg jonatansberg commented Jun 24, 2026

Copy link
Copy Markdown
Member

ref https://linear.app/ghost/issue/BER-3746/integrate-gift-link-usage-tracking-with-analytics

Ghost's Gift Links feature is moving usage tracking off a bespoke DB counter and onto the existing web-analytics pipeline, so gift numbers are measured the same way as every other page view. Gift reads carry one new dimension — gift (the gift-link token) — on the page_hit payload, so the data can:

  • segment "gift traffic" in the normal reports, and
  • count usage per individual link.

Why this PR is needed

The proxy rebuilds the payload field-by-field (pageHitRawPayloadFromRequesttransformPageHitRawToProcessed), so any field not explicitly threaded is silently dropped before it reaches Tinybird. This wires gift through end-to-end:

  • schemas/v1/page-hit-raw.tsgift on PayloadSchema (optional, nullable).
  • transformations/page-hit-transformations.ts — copied in pageHitRawPayloadFromRequest(), defaulting to null.
  • schemas/v1/page-hit-processed.ts — on PageHitProcessedSchema and the payload rebuilt in transformPageHitRawToProcessed().
  • schemas/v1/page-hit-request.ts — declared explicitly (validation already admits it via additionalProperties: true) + a null default.

Covers both the inline and batch worker paths, since both run through these transforms. Absent on non-gift hits, where it defaults to null.

Notes for review

  • gift is the gift-link token, a bearer credential — but first-party data the site owner already minted and shareable by design, so storing it in their own analytics is acceptable. Worth a thought on error-log / retention.
  • Producer (Ghost ghost_head) and the Tinybird data-files (_mv_hits column, segment, per-link endpoint) are separate PRs on the Ghost repo. This PR is a safe no-op until those land.

Tests

tsc clean. page-hit-transformations.test.ts: the "all fields present" case now asserts gift passthrough, plus a new case for the absent → null default. (The 2 pre-existing SaltStoreFactory failures are unrelated Firestore/GCP-env tests.)

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a8ff4ebd-a7ef-4879-a839-634ab3cc45d0

📥 Commits

Reviewing files that changed from the base of the PR and between 8015d8b and 819aaa5.

📒 Files selected for processing (5)
  • src/schemas/v1/page-hit-processed.ts
  • src/schemas/v1/page-hit-raw.ts
  • src/schemas/v1/page-hit-request.ts
  • src/transformations/page-hit-transformations.ts
  • test/unit/transformations/page-hit-transformations.test.ts
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/schemas/v1/page-hit-raw.ts
  • src/schemas/v1/page-hit-processed.ts
  • src/schemas/v1/page-hit-request.ts
  • src/transformations/page-hit-transformations.ts
  • test/unit/transformations/page-hit-transformations.test.ts

Walkthrough

The page-hit request, raw, and processed payload schemas now include an optional nullable gift_link field. The request payload defaults now set gift_link to null when omitted. The request-to-raw transformation copies gift_link from the request body with a null fallback, and the raw-to-processed transformation copies gift_link into the processed payload. Unit tests were updated for the populated and missing gift_link cases.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: threading the gift field through the page hit pipeline.
Description check ✅ Passed The description is directly related to the changeset and accurately explains the gift field passthrough work.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ber-3728-gift-id-passthrough

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@jonatansberg jonatansberg force-pushed the ber-3728-gift-id-passthrough branch from c4b255c to 9b85789 Compare June 24, 2026 10:49
@jonatansberg jonatansberg changed the title Pass gift_id through the page hit pipeline Pass gift through the page hit pipeline Jun 24, 2026
@jonatansberg jonatansberg force-pushed the ber-3728-gift-id-passthrough branch from 9b85789 to a1e6503 Compare June 24, 2026 13:45
@jonatansberg jonatansberg marked this pull request as ready for review June 25, 2026 14:50
@jonatansberg jonatansberg requested a review from cmraible as a code owner June 25, 2026 14:50

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a1e6503b9d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/schemas/v1/page-hit-processed.ts Outdated
@jonatansberg jonatansberg force-pushed the ber-3728-gift-id-passthrough branch from a1e6503 to 95c51f3 Compare June 25, 2026 14:58

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 95c51f3892

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/transformations/page-hit-transformations.ts Outdated
Comment thread src/schemas/v1/page-hit-processed.ts Outdated
Comment thread src/schemas/v1/page-hit-processed.ts Outdated
@jonatansberg jonatansberg force-pushed the ber-3728-gift-id-passthrough branch from 95c51f3 to 8015d8b Compare June 29, 2026 09:43

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/schemas/v1/page-hit-processed.ts`:
- Line 166: The processed payload mapping in PageHitProcessed still forwards
pageHitRaw.payload.gift_link directly, which can leave it undefined instead of
normalizing to null. Update the page-hit processing transform to apply the same
fallback used in the request-to-raw path so that missing gift_link values become
null consistently in the processed output.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 05ef0f0b-5e3b-4d8d-970d-c8e3e296f8f6

📥 Commits

Reviewing files that changed from the base of the PR and between a1e6503 and 8015d8b.

📒 Files selected for processing (5)
  • src/schemas/v1/page-hit-processed.ts
  • src/schemas/v1/page-hit-raw.ts
  • src/schemas/v1/page-hit-request.ts
  • src/transformations/page-hit-transformations.ts
  • test/unit/transformations/page-hit-transformations.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/schemas/v1/page-hit-raw.ts

member_status: pageHitRaw.payload.member_status,
post_uuid: pageHitRaw.payload.post_uuid,
post_type: pageHitRaw.payload.post_type,
gift_link: pageHitRaw.payload.gift_link,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Normalize missing raw gift_link to null here too.

PageHitRaw.payload.gift_link is optional upstream, so the batch/raw path can still hand you undefined. Copying it through directly breaks the PR’s “absent => null” contract for processed payloads. Use the same fallback as the request→raw transform.

Suggested fix
-            gift_link: pageHitRaw.payload.gift_link,
+            gift_link: pageHitRaw.payload.gift_link ?? null,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
gift_link: pageHitRaw.payload.gift_link,
gift_link: pageHitRaw.payload.gift_link ?? null,
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/schemas/v1/page-hit-processed.ts` at line 166, The processed payload
mapping in PageHitProcessed still forwards pageHitRaw.payload.gift_link
directly, which can leave it undefined instead of normalizing to null. Update
the page-hit processing transform to apply the same fallback used in the
request-to-raw path so that missing gift_link values become null consistently in
the processed output.

ref https://linear.app/ghost/issue/BER-3746/integrate-gift-link-usage-tracking-with-analytics

Ghost is moving gift-link usage tracking onto the existing web-analytics
pipeline. Gift reads now carry a `gift_link` field (the gift-link token) on the
page_hit payload so the data can segment gift traffic and count per-link usage.

The proxy rebuilds the payload field-by-field, so an un-threaded field is
silently dropped before it reaches Tinybird. This threads `gift_link` (optional,
nullable) through the raw schema, the raw-payload transform, the processed
schema, and the request schema/defaults — covering both the inline and batch
worker paths. Absent on non-gift hits, where it defaults to null.
@jonatansberg jonatansberg force-pushed the ber-3728-gift-id-passthrough branch from 8015d8b to 819aaa5 Compare June 29, 2026 12:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 819aaa5fb3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

member_status: request.body.payload.member_status,
post_uuid: request.body.payload.post_uuid,
post_type: request.body.payload.post_type,
gift_link: request.body.payload.gift_link ?? null,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Read the gift token from the producer field

When Ghost sends the new gift-link dimension as payload.gift (as described by this change and allowed by the request schema's additionalProperties), this transform only reads payload.gift_link, so gift_link becomes null and the raw/processed events never carry the token to Tinybird. For gift-link page hits this makes the new per-link analytics silently report as non-gift traffic unless the producer is changed to the different field name.

Useful? React with 👍 / 👎.

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.

2 participants