Skip to content

feat: SDK Automatic Push Behavior Integration (rel/4.5.0)#517

Draft
glenn-klaviyo wants to merge 12 commits into
rel/4.5.0from
feat/auto-push-tracking
Draft

feat: SDK Automatic Push Behavior Integration (rel/4.5.0)#517
glenn-klaviyo wants to merge 12 commits into
rel/4.5.0from
feat/auto-push-tracking

Conversation

@glenn-klaviyo

Copy link
Copy Markdown

All work associated with Automatic Push Behavior Integration

#493
#495
#500
#503
#506
#507
#508
#509
#512
#513
#516

glenn-klaviyo and others added 9 commits June 29, 2026 19:22
…king [MAGE-767] (#493)

* feat(core): add getManifestBoolean and automatic push tracking key

Add a Config.getManifestBoolean accessor (interface + KlaviyoConfig
override + Context extension mirroring getManifestInt) and the
Constants.AUTOMATIC_PUSH_TRACKING manifest key ("com.klaviyo.automatic_push_tracking").

The key lives in core because push token telemetry must read it and core
cannot depend on push-fcm. BaseTest mocks getManifestBoolean to return the
supplied default so existing suites run with the flag off. The config test
covers both the Tiramisu and pre-Tiramisu getApplicationInfo paths.

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

* feat(push): route taps through trampoline for automatic open tracking

Extend KlaviyoTrampolineActivity (from #448) so that, when a host opts in
via the com.klaviyo.automatic_push_tracking manifest flag, body / deep_link /
open_app taps route through the trampoline, which calls Klaviyo.handlePush
itself — removing the need for handlePush in host Activities.

- forDestination intent factory (setClassName test seam) shared by body and
  button intents; deep link carried as intent data.
- handleTrampolineIntent dispatches on intent contents: browser URL (unchanged,
  #448) else deep-link-via-VIEW (when no DeepLinkHandler) / launch fallback.
- onNewIntent override + Xiaomi-safe finish posted after dispatch.
- Manifest: singleTask + taskAffinity="" + excludeFromRecents.
- KlaviyoNotification reads the flag once per build and routes body/button
  intents accordingly; flag off is byte-identical to today, open_url always
  routes through the trampoline regardless of the flag.

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

* test: assert extras parity on trampoline routing and strengthen config test

- KlaviyoNotificationTest: when automatic tracking is on, assert the body and
  action-button intents routed through KlaviyoTrampolineActivity still carry the
  Klaviyo extras (and the notification tag for buttons), matching the flag-off path.
- KlaviyoConfigTest: back the metadata Bundle with a real map so getManifestBoolean
  is verified against genuine present/absent semantics rather than a stubbed echo.

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

* revert(push): drop Xiaomi runOnUiThread finish workaround

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

* docs(push): clarify deep link is kept for handler when unresolvable

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

* fix(push): sanitize trampoline logs and preserve CLEAR_TOP on forward

- Drop URL/deep-link interpolation from dispatch logs (keep branch label)
- Carry CLEAR_TOP onto the forwarded destination for back-stack parity

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

* fix(core): don't log full intent on unresolved startActivity

Intent.toString() includes data/extras which can carry payload-derived
URLs (deep links, browser URLs) with tokens. Log action+component only.

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

* test(fixtures): stub Intent.component getter in MockIntent

The sanitized startActivityIfResolved log reads intent.component; the
mockkConstructor mock threw on the unstubbed getter, breaking DeepLinkingTest.

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

* fix(push): read auto-tracking flag from build-time context

- Read the manifest flag via context.getManifestBoolean in buildNotification
  so opt-in works even if FCM builds a notification before Klaviyo.initialize
  (Registry.config returns the default until init). Mirrors getManifestInt usage.
- MockIntent: mirror Android by exposing a ComponentName via component after
  setClassName, instead of null.

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

* fix(push): log deep-link launcher fallback at warning not error

Degraded-but-handled fallback per the logging-severity convention.

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

* docs(push): trim verbose comments per review feedback

- Condense intent-logging, manifest-flag, and auto-tracking comments
- Drop redundant re-export cross-reference in Constants
- Add lead-in framing for the opt-in manifest snippet
- Document the trampoline activity's invisible/transient manifest attrs

-Claude

* docs(push): describe trampoline manifest attrs individually

Replace the open-tracking-focused block comment with a neutral summary
plus a per-attribute reference, since the trampoline also routes deep
links and URLs.

-Claude

* docs(push): drop manifest snippet from auto-tracking const KDoc

Integration how-to belongs in the dev docs, not the KDoc; sibling
METADATA_* consts carry none. Keep a one-line description since the
opt-in behavior is non-obvious.

-Claude

* fix(push): warn when trampoline finds no host launch intent

Restores diagnostic parity with the non-trampoline path: when automatic
push tracking is on and the host has no launcher activity,
makeLaunchIntent returns null and startDestination silently no-ops.
Log a warning so the missing launcher is still debuggable. No behavior
change otherwise — the open is still tracked and nothing crashes.

-Claude

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…68) (#495)

* feat(push): dedup auto-tracked push opens via in-memory delivery guard

Adds an in-memory guard so a single notification tap tracks one
$opened_push even when a host opts into the trampoline but leaves a
manual Klaviyo.handlePush call in place.

The guard keys on the per-delivery tm field of the _k tracking payload,
falling back to an SDK-generated per-notification UUID stamped on the
trampoline intent when tm is absent (local notifications, previews, and
other non-campaign sends). Both keys ride forward onto the host's
destination intent, so the trampoline's handlePush and the host's manual
call resolve to the same key and collapse to one event/dismissal/deep
-link dispatch, while distinct notifications never collide.

The guard engages only for intents the trampoline marks as auto-tracked,
so manual-only integrations behave exactly as before. open_url is left
unmarked: it always trampolines regardless of the flag and the host never
receives a forwarded open_url tap, so there is nothing to deduplicate.

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

* test(push): DRY up BoundedIdSet concurrency test harness

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

* test(push): surface worker failures in BoundedIdSet concurrency harness

Count down in finally and assert collected worker throwables after await,
so a failing worker reports its real cause instead of a misleading timeout.

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

* refactor(push): flatten handlePush with early-return guards; tighten dedup docs

Address review feedback: replace the safeApply/takeIf/elvis chain with
early-return guards and a single State lookup, keeping safeApply on each
side effect so the SDK never crashes the host. Reword the dedup guard
comment, trim the constant/property docs to point at the logic, and drop
the raw delivery id from the duplicate-open log.

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

* refactor(push): dedupe all Klaviyo opens by delivery id

Address review: drop the auto-tracked marker gate and dedupe every
Klaviyo push open on its delivery id, so the trampoline call and a host's
manual handlePush collapse to one open regardless of ordering or marker
propagation. Reorder so the isKlaviyoNotificationIntent guard runs first.
Removes NOTIFICATION_AUTO_TRACKED_EXTRA and isAutoTrackedOpen; the
generated NOTIFICATION_UID_EXTRA remains as the tm-less fallback key.

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

* refactor(core): guard BoundedIdSet with a private lock

Lock on a private monitor instead of the instance (@synchronized), so
external holders can't contend with or deadlock the internal locking.

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

* feat(push): stamp a per-notification dedup id on all tap intents

Extend the tm-less fallback dedup key to every notification, not just
trampoline ones: generate one NOTIFICATION_UID_EXTRA per notification in
buildNotification and stamp it on the body and every action-button intent
(auto-tracking or not). handlePush now dedupes any notification's opens
by tm, else this id — so a manual handlePush called twice on the same
tm-less notification collapses to one open. Body and buttons of a
notification share the id (distinct notifications differ), so distinct
targets no longer split. Moves the stamp out of the trampoline factory.

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

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…follow-up) (#500)

* refactor(push): extract push-open handling from Klaviyo into KlaviyoPushOpenHandler

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(push): move handlePush tests into KlaviyoPushOpenHandlerTest

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* test(push): address CodeRabbit feedback on KlaviyoPushOpenHandlerTest

- Add coverage for the notification-dismissal branch
- Replace !! with requireNotNull for _k extra lookups
- Assert warning log level rather than exact message text
- Drop redundant Registry.unregister<Config>() in cleanup

-Claude

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(push): automatic push token registration (MAGE-769)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(push): namespace automatic push tracking manifest keys under com.klaviyo.push.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(push): broaden fetcher error handling to honor must-not-throw contract

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(push): address review nits — method name, provider params, test DRY

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(push): dedupe registerMockPushTokenFetcher into BaseTest

-Claude

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…(MAGE-765) (#506)

* feat(push): add X-Klaviyo-Sdk-Features header to push-token-register (MAGE-765)

Reports when a host has explicitly disabled automatic push token
forwarding while automatic push tracking is on, so the backend can
track opt-out adoption (MAGE-766). Scoped to PushTokenApiRequest only;
omitted entirely when tracking is off or forwarding is left at its
default-on state, since only the opt-out case needs reporting.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(push): always send both SDK feature flags in push-token header (MAGE-765)

Previously the X-Klaviyo-Sdk-Features header was omitted unless
automatic push tracking was on and forwarding was disabled, carrying
only the forwarding key. Now it's always attached with both
auto_push_tracking and auto_push_token_forwarding so all four flag
combinations are visible for analysis, not just the opt-out case.

auto_push_token_forwarding now mirrors the disable flag directly
(1 unless explicitly disabled), independent of the tracking flag.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* feat(push): only include SDK feature flags whose manifest key is set (MAGE-765)

Previously both auto_push_tracking and auto_push_token_forwarding were
always present in X-Klaviyo-Sdk-Features, falling back to a default
value when the host hadn't set the corresponding manifest key. Now
each attribute is included only if its manifest key is actually
declared, so the header reflects what the host explicitly configured
rather than an assumed default.

Adds Config.hasManifestKey(key) (mirroring getManifestBoolean/Int) to
distinguish "key absent" from "key present and false", which
getManifestBoolean's single default-value return couldn't do.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* fix(core): resolve duplicate DISABLE_AUTOMATIC_TOKEN_FORWARDING after merge

The merge from feat/auto-push-tracking (PR #503) landed a second
declaration of this constant without a git conflict, since both
additions fell in non-overlapping diff hunks. Keeps PR #503's
PUSH_PREFIX-based definition, which is also the one Klaviyo.kt
actually uses to gate automatic push token registration; our header
logic already references the constant by name, so no other change is
needed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

* refactor(core): extract scoped SdkFeatures catalog for X-Klaviyo-Sdk-Features (MAGE-765)

Replaces the inline header-building in PushTokenApiRequest with a
reusable, scoped feature catalog in core, mirroring the iOS design
(klaviyo-swift-sdk#640) for cross-platform parity.

- SdkFeatureScope enumerates the request surfaces a feature is reported
  on; SdkFeatureKey is a central catalog pairing each feature's wire
  name with its manifest key, scope, and raw->reported value mapping.
- SdkFeatures.headerValue(scope) serializes only in-scope features whose
  manifest key is present, so a feature can never leak onto a request
  outside its scope. Adding a future (e.g. profile) feature header is a
  new key + scope, reusing the same serialization.

Pure refactor: the emitted header is byte-identical for every manifest
combination. Existing PushTokenApiRequestTest/EventApiRequestTest pass
unchanged as the regression guard; SdkFeaturesTest covers the catalog.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
* docs(readme): document automatic push integration (MAGE-771)

Restructure the Push Notifications section to lead with the zero-boilerplate
automatic integration (Option A) while preserving the manual path (Option B).

- Add a "Which option?" callout and an Option A section covering the
  com.klaviyo.push.automatic_push_tracking manifest flag, automatic open
  tracking via the trampoline, and token registration at initialize() and on
  each foreground, plus the disable_automatic_token_forwarding opt-out.
- Correct the onNewToken wording: it only fires on token generation/rotation,
  so it can miss a pre-existing token or when FCM auto-init is disabled.
- Update the table of contents with Option A / Option B anchors.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(readme): trim Option A push notes (MAGE-771)

Remove the token de-dup detail, the initialize() reminder, the optional
DeepLinkHandler subsection, and the MAGE-708 broadcast-reception aside from
the automatic integration section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(readme): address PR review feedback (MAGE-771)

- Soften "token rotations are always caught" to "picked up on those events".
- Scope the disable_automatic_token_forwarding claim to the init/foreground
  fetch, and note onNewToken still forwards while KlaviyoPushService is the
  registered FCM service.
- Clarify that onNewToken only forwards when KlaviyoPushService is the
  registered FCM service; custom services must call setPushToken themselves.
- Link the sample-app TODO to MAGE-770.
- Nest Collecting Push Tokens and Receiving Push Notifications under Option B
  (and matching TOC) so Option B is no longer an empty wrapper.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…n (MAGE-770) (#508)

* feat(sample): product flavors for manual vs automatic push integration (MAGE-770)

Add an `integration` flavor dimension with `manual` and `automatic` flavors so the
sample demonstrates both Klaviyo push integration styles side by side, mirroring the
iOS SPMExample / SPMExampleAutomatic split.

- manual: unchanged Option B path (app fetches the FCM token + calls setPushToken, and
  calls Klaviyo.handlePush(intent) on notification taps).
- automatic: opts in via the com.klaviyo.push.automatic_push_tracking manifest flag; the
  SDK auto-registers the token at initialize()/foreground and routes taps through
  KlaviyoTrampolineActivity, so SampleActivity carries zero push boilerplate.

SampleActivity.kt moves out of src/main into each flavor source set (AGP can't exclude a
main class per flavor); everything else stays shared under src/main. README documents how
to switch build variants.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(sample): refresh auto-registered push token in UI on resume (MAGE-770)

The automatic flavor never calls updatePushToken (the SDK auto-registers the token
asynchronously), and SampleViewModel only seeded pushToken once at construction, so the
Push Token field could stay empty even though registration succeeded.

Re-read Klaviyo.getPushToken() from the existing ON_RESUME lifecycle observer in SampleView
so the displayed token reflects the auto-registered value. Shared code only — the automatic
SampleActivity stays free of push boilerplate. Only overwrites when the SDK has a token, so a
shown value is never clobbered with an empty one.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(sample): drop iOS example reference from flavor docs (MAGE-770)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(sample): fix stale build.gradle link in README (MAGE-770)

Line 56 still pointed at ./build.gradle; the file uses the Kotlin DSL
extension. Matches the corrected link on line 12. Flagged by CodeRabbit.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(push): decouple auto push tracking and token forwarding (MAGE-886) (#509)

* feat(push): decouple auto push tracking and token forwarding (MAGE-886)

Replace the nested `disable_automatic_token_forwarding` escape hatch with a
fully independent opt-in flag `automatic_token_forwarding`. The two push flags
are now orthogonal:

- `automatic_push_tracking` gates only automatic open tracking (trampoline)
- `automatic_token_forwarding` gates only automatic token fetch/forwarding

Both flags are unshipped (feature branch only), so there is no backward-compat
cost. `KlaviyoPushService.onNewToken()` still forwards unconditionally; hosts
opt out by registering their own FirebaseMessagingService.

Also retargets the SdkFeatures telemetry entry to the new flag (dropping the
inverted reportedValue); the `auto_push_token_forwarding` wire name is
unchanged so the backend contract is preserved.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(push): address review feedback on docs/comments (MAGE-886)

Per review on #509:
- Drop the added KDoc block on KlaviyoPushService.onNewToken()
- Remove flag-independence note from Constants KDoc (belongs in README)
- Stop exposing internal KlaviyoTrampolineActivity in sample docs; describe
  the behavior at the public API level (Klaviyo.handlePush) instead

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(sample): set automatic flavor push flags to true (MAGE-886)

The automatic flavor manifest had both automatic_push_tracking and
automatic_token_forwarding at false, so automaticDebug behaved like the
manual flavor despite the Option A docs. Restore both to true to match the
intended automatic integration and the sample/PR documentation.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* docs(readme): document decoupled push flags (MAGE-888)

Update the root README Push Notifications section for the independent
push flags introduced in MAGE-886 (#509):

- Option A now enables both automatic_push_tracking and the new opt-in
  automatic_token_forwarding
- Replace the removed disable_automatic_token_forwarding opt-out with an
  "independent flags" section documenting all four valid combinations
- Describe open tracking at the API level (Opened Push / handlePush)
  instead of naming internal implementation
- Link the sample app's automatic product flavor as a runnable reference

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(readme): drop four-combination flag table (MAGE-888)

Per review feedback, remove the verbose flag-combination table; the
surrounding prose already explains the independent opt-ins and the
mixed-flag case, matching the iOS README.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…-932) (#513)

* refactor(push): rename automatic push integration manifest keys (MAGE-932)

Rename the two opt-in push-integration manifest <meta-data> keys for clarity:
- com.klaviyo.push.automatic_push_tracking -> com.klaviyo.push.automatic_push_open_tracking
- com.klaviyo.push.automatic_token_forwarding -> com.klaviyo.push.automatic_push_token_forwarding

Also renames the corresponding Kotlin constants/aliases and updates the sample
app and README docs. The X-Klaviyo-Sdk-Features wire names (auto_push_tracking,
auto_push_token_forwarding) are intentionally left unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test: rename push-flag test helpers to match renamed constants

- setAutomaticPushTracking -> setAutomaticPushOpenTracking
- setTokenForwardingEnabled -> setAutomaticPushTokenForwardingEnabled
- enableAutomaticTracking -> enableAutomaticPushOpenTracking

Addresses CodeRabbit review feedback on #513.

-Claude

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 21, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 047f1cf5-fbad-4271-9e95-211fa2eb5ee2

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/auto-push-tracking

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

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 816f86c. Configure here.

Comment thread sdk/push-fcm/src/main/java/com/klaviyo/pushFcm/KlaviyoRemoteMessage.kt Outdated
@glenn-klaviyo glenn-klaviyo added the SDK Auto Integration A label for the SDK Auto Integration project - automatic push open tracking and token forwarding label Jul 21, 2026
Atharva8168 and others added 3 commits July 23, 2026 12:03
…Token (MAGE-937) (#516)

* feat(push): default automatic_push_token_forwarding ON and gate onNewToken (MAGE-937)

Flip automatic_push_token_forwarding to default ON and route both automatic
token-collection paths — the initialize/foreground fetch and
KlaviyoPushService.onNewToken — through a single shared gate
(isAutomaticPushTokenForwardingEnabled in core), so
automatic_push_token_forwarding="false" is a complete opt-out. The public
Klaviyo.setPushToken API and SdkFeatures telemetry are intentionally unchanged.

Update the sample manual flavor to opt out explicitly and reconcile the root and
sample READMEs to document the default-ON behavior.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(push): read token-forwarding flag from Context in onNewToken to avoid pre-init crash (MAGE-937)

KlaviyoPushService.onNewToken can fire before Klaviyo.initialize (FCM may deliver a
token at process start), so gating it via Registry.config threw MissingConfig out of
the messaging service. Read the flag from the service Context instead — mirroring how
KlaviyoNotification reads the sibling open-tracking flag — which is safe pre-init and
still honors the opt-out.

The analytics path (Klaviyo.maybeAutoRegisterPushToken) keeps reading via Registry.config
(always post-initialization). Both paths share Constants.AUTOMATIC_PUSH_TOKEN_FORWARDING
and the new Constants.AUTOMATIC_PUSH_TOKEN_FORWARDING_DEFAULT so their default can't drift,
consistent with how the sibling open-tracking flag is read per-module.

Addresses Cursor Bugbot finding on PR #516.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* docs(readme): generalize push-provider examples in sample README (MAGE-937)

Address review feedback: replace the specific "Braze/Airship/Iterable" list with
"other push providers" in the sample README's token-forwarding note.

-Claude

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
… guide + README (#520)

* docs: add 4.4.0 automatic push tracking flags migration guide and README note

- Add migration guide entry for `automatic_push_open_tracking` (opt-in, default off)
  and `automatic_push_token_forwarding` (default on, pending #516/MAGE-937 merge)
- Token-forwarding entry is explicitly marked pending klaviyo-android-sdk#516;
  finalize on merge before releasing docs
- Add two-stage rollout summary table covering both Android and iOS flags
- Add anonymous-profile note to README Anonymous Tracking section

Relates to MAGE-897.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: drop pending-#516 caveats from Android migration guide

MAGE-937 (#516) is landing imminently; remove the "pending merge" note,
heading suffix, and table caveat, and fix the README anchor link.

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

* docs: fix Anonymous Tracking anchor to point at the README

Bare `#anonymous-tracking` fragment resolved against MIGRATION_GUIDE.md;
link explicitly to ./README.md#anonymous-tracking.

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

* docs: correct token-forwarding timing to init/foreground/refresh

Per maybeAutoRegisterPushToken (called from initialize and on app foreground)
plus onNewToken: the SDK forwards the current token at initialization, on
foreground, and on FCM token refresh — not only "as soon as FCM delivers one".

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

* docs: correct auto-push release version to 4.5.0 (Android)

The automatic push behaviors ship in the upcoming 4.5.0 minor, not 4.4.0.
Updated the migration guide section and the README anonymous-profile note;
left install snippets and unrelated version references untouched.

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

* docs: Android-only migration guide + clarify default-on token forwarding

- Remove iOS flag rows from the rollout summary (Android guide should not
  document iOS behavior).
- Reword the intro to distinguish the opt-in open-tracking flag from the
  default-on token forwarding, and note the manual-control opt-out
  (addresses CodeRabbit).

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

* docs: move opt-in/out instructions to README, point migration guide there

Per review feedback: configuration instructions (XML snippets) belong in
the README alongside the existing Option A setup guide; the migration
guide now links there instead of duplicating them.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Resolves conflicts in KlaviyoTrampolineActivity and its test by keeping
the expanded dispatch logic from feat/auto-push-tracking and adopting the
makeBrowserIntent → makeExternalIntent rename from feat/push-trampoline.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

SDK Auto Integration A label for the SDK Auto Integration project - automatic push open tracking and token forwarding

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants