Skip to content

feat(inbox): type trackingIds and add clickTrackingId for SDK parity - #64

Open
mikemilla wants to merge 1 commit into
mainfrom
mike/c-19804-rn-typed-tracking-ids
Open

feat(inbox): type trackingIds and add clickTrackingId for SDK parity#64
mikemilla wants to merge 1 commit into
mainfrom
mike/c-19804-rn-typed-tracking-ids

Conversation

@mikemilla

Copy link
Copy Markdown
Collaborator

Ticket: C-19804

Not a bug fix — worth saying plainly

Unlike courier-flutter (which genuinely had no trackingIds field), this SDK was never broken:

  • InboxMessage already declared trackingIds
  • fromJson already passes parsed.trackingIds into the constructor, so the field the native SDKs send has always reached JS
  • the high-level Courier.shared.clickMessage({ messageId }) resolves the tracking id natively, so click tracking worked regardless

I initially reported the opposite on C-19804 — that was wrong, from globbing *.ts and missing .tsx. Retracted there.

What was actually missing: reachability

before after
trackingIds type { [key: string]: any } — guess the key names, no autocomplete, no compiler check InboxMessageTrackingIds, all seven ids
clickTrackingId absent — only SDK without it present, matching ios / android / flutter

That matters for the lower-level client.inbox.click({ messageId, trackingId }), which does need the id — and this was the only SDK where you had to reach through an untyped map to get it.

Change

  • InboxMessageTrackingIds covering all seven ids the server publishes: archive, channel, click, deliver, open, read, unread — exported as a type
  • trackingIds field and constructor parameter typed to it
  • clickTrackingId getter for parity

Read from the root of the message, where both the GraphQL read and the iwpv=v2 socket publish it. Independent of the protocol version and of the pending native pin bump.

Tests

130/130 passing, tsc --noEmit clean, eslint clean. 5 new cases:

  • all seven ids parsed from a native payload
  • clickTrackingId present, absent, and present-but-partial
  • a nested data.trackingIds copy (the v1/legacy shape) is not read

One of these caught a wrong assumption of mine while writing it: fromJson passes undefined into a parameter defaulting to null, so an absent trackingIds lands as null, not undefined. The test now pins that actual behaviour.

🤖 Generated with Claude Code

Not a bug fix — worth saying plainly, because it looked like one.

Unlike courier-flutter, this SDK was never broken. `InboxMessage` already declared
`trackingIds`, and `fromJson` already passes `parsed.trackingIds` into the
constructor, so the field the native SDKs send has always reached JS. The
high-level `Courier.shared.clickMessage({ messageId })` also resolves the tracking
id natively, so click tracking worked regardless.

What was missing was reachability. `trackingIds` was typed `{ [key: string]: any }`,
so a caller using the lower-level `client.inbox.click({ messageId, trackingId })`
had to guess key names off an untyped map with no autocomplete and no compiler
check. And `clickTrackingId` — a convenience that exists on courier-ios,
courier-android and now courier-flutter — had no equivalent here, making this the
only SDK where you had to reach through the map by hand.

- `InboxMessageTrackingIds` covering all seven ids the server publishes (archive,
  channel, click, deliver, open, read, unread), exported as a type
- `trackingIds` field and constructor parameter typed to it
- `clickTrackingId` getter, matching the other SDKs

Reads from the root of the message, which is where both the GraphQL read and the
`iwpv=v2` socket publish it. Nothing here depends on the protocol version or on a
native SDK release, so this is independent of the pending pin bump.

Tests: 5 new cases (all seven ids parsed, clickTrackingId present/absent/partial,
and that a nested `data.trackingIds` copy — the v1/legacy shape — is not read).
130/130 passing, `tsc --noEmit` clean, eslint clean.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@linear

linear Bot commented Aug 5, 2026

Copy link
Copy Markdown

C-19804

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant