@@ -25,13 +25,15 @@ send them timely push notifications via [FCM (Firebase Cloud Messaging)](https:/
2525- [ Push Notifications] ( #push-notifications )
2626 - [ Prerequisites] ( #prerequisites )
2727 - [ Setup] ( #setup )
28- - [ Collecting Push Tokens] ( #collecting-push-tokens )
29- - [ Receiving Push Notifications] ( #receiving-push-notifications )
30- - [ Rich Push] ( #rich-push )
31- - [ Push Action Buttons] ( #push-action-buttons )
32- - [ Tracking Open Events] ( #tracking-open-events )
33- - [ Silent Push Notifications] ( #silent-push-notifications )
34- - [ Custom Data] ( #custom-data )
28+ - [ Option A — Automatic integration] ( #option-a--automatic-integration )
29+ - [ Option B — Manual integration] ( #option-b--manual-integration )
30+ - [ Collecting Push Tokens] ( #collecting-push-tokens )
31+ - [ Receiving Push Notifications] ( #receiving-push-notifications )
32+ - [ Rich Push] ( #rich-push )
33+ - [ Push Action Buttons] ( #push-action-buttons )
34+ - [ Tracking Open Events] ( #tracking-open-events )
35+ - [ Silent Push Notifications] ( #silent-push-notifications )
36+ - [ Custom Data] ( #custom-data )
3537 - [ Advanced Setup] ( #advanced-setup )
3638- [ In-App Forms] ( #in-app-forms )
3739 - [ Prerequisites] ( #prerequisites-1 )
@@ -393,6 +395,16 @@ Additional event properties can be specified as part of the `Event` object:
393395- Klaviyo ` analytics ` and ` push-fcm ` packages
394396- If you expect to use deep links in your push notifications, see the [ deep linking] ( #deep-linking ) section below.
395397
398+ > ** Which option should I use?**
399+ >
400+ > Choose ** Option A — Automatic integration** for a minimal-boilerplate setup. With a single
401+ > manifest flag, the SDK tracks push opens automatically and registers the push token for you —
402+ > no ` Klaviyo.handlePush() ` calls and no manual token wiring.
403+ >
404+ > Choose ** Option B — Manual integration** if you need direct control over token collection or
405+ > intent handling — for example, a custom ` FirebaseMessagingService ` , a bespoke deep-link/intent
406+ > flow, or an app that manages its own push-token pipeline.
407+
396408### Setup
397409
398410To specify an icon and/or color for Klaviyo notifications, add the following optional metadata elements to the
@@ -414,12 +426,98 @@ will be used if present, else we fall back on the application's launcher icon, a
414426</manifest >
415427```
416428
417- ### Collecting Push Tokens
429+ ### Option A — Automatic integration
430+
431+ With automatic push tracking enabled, the Klaviyo SDK handles the two pieces of push integration
432+ that otherwise require boilerplate in your app code:
433+
434+ - ** Push open tracking** — Klaviyo notification taps are routed through an internal trampoline
435+ activity that records the ` Opened Push ` event for you, then forwards the user to their
436+ destination. You do ** not** need to call ` Klaviyo.handlePush(intent) ` anywhere.
437+ - ** Push token registration** — the SDK fetches the current FCM token and registers it with
438+ Klaviyo automatically, so you don't need to call ` Klaviyo.setPushToken(...) ` yourself.
439+
440+ #### Step 1 — Enable automatic push tracking in ` AndroidManifest.xml `
441+
442+ Add the following meta-data to the ` <application> ` element. Note the ` com.klaviyo.push. `
443+ namespace — it matches the existing Klaviyo notification meta-data keys. ** The exact key is
444+ required** ; a bare ` com.klaviyo.automatic_push_tracking ` (without the ` push. ` segment) is
445+ silently ignored.
446+
447+ ``` xml
448+ <!-- AndroidManifest.xml -->
449+ <manifest >
450+ <!-- ... -->
451+ <application >
452+ <!-- ... -->
453+ <meta-data
454+ android : name =" com.klaviyo.push.automatic_push_tracking"
455+ android : value =" true" />
456+ </application >
457+ </manifest >
458+ ```
459+
460+ #### Step 2 — Initialize the SDK
461+
462+ ``` kotlin
463+ import com.klaviyo.analytics.Klaviyo
464+
465+ Klaviyo .initialize(" YOUR_PUBLIC_API_KEY" , applicationContext)
466+ ```
467+
468+ That's it. With the flag set, ` initialize() ` covers both concerns above:
469+
470+ - ** Open tracking** is handled by the trampoline for every Klaviyo notification tap.
471+ - ** Token registration** happens at ` initialize() ` ** and** again on every app foreground, so
472+ token rotations are picked up on those events.
473+
474+ #### Displaying notifications
475+
476+ The automatic flag removes the manual ** token wiring** and ** ` handlePush() ` ** calls — it does
477+ ** not** remove the requirement to * receive and display* notifications. ` KlaviyoPushService ` is
478+ still what displays Klaviyo notifications, and it is registered automatically by the SDK unless
479+ your app provides its own ` FirebaseMessagingService ` (see [ Advanced Setup] ( #advanced-setup ) ).
480+
481+ If you run multiple push providers and don't register ` KlaviyoPushService ` , automatic ** token
482+ registration** still works standalone — but Klaviyo message ** display** requires the service.
483+
484+ #### Advanced: disable automatic token forwarding
485+
486+ If your app owns its own push-token pipeline (for example, forwarding a single token to multiple
487+ providers) but you still want automatic open tracking, opt out of token forwarding with an
488+ additional meta-data flag. Open tracking is unaffected; the SDK stops the automatic
489+ init/foreground token fetch, and you register the token yourself via ` Klaviyo.setPushToken(...) `
490+ as in Option B.
491+
492+ ``` xml
493+ <meta-data
494+ android : name =" com.klaviyo.push.disable_automatic_token_forwarding"
495+ android : value =" true" />
496+ ```
497+
498+ This flag gates only the automatic init/foreground fetch. If ` KlaviyoPushService ` remains your
499+ registered FCM service, its ` onNewToken ` will still forward newly generated or rotated tokens to
500+ Klaviyo. To fully own the token pipeline, register your own ` FirebaseMessagingService ` (see
501+ [ Advanced Setup] ( #advanced-setup ) ) so ` KlaviyoPushService.onNewToken ` never runs.
502+
503+ <!-- TODO(MAGE-770 — https://linear.app/klaviyo/issue/MAGE-770): once the sample app's `automatic`
504+ product flavor is merged, link it here as the runnable reference for Option A (the
505+ `automatic` flavor under `sample/`). -->
506+
507+ ### Option B — Manual integration
508+
509+ #### Collecting Push Tokens
418510In order to send push notifications to your users, you must collect their push tokens and register them with Klaviyo.
419511This is done via the ` Klaviyo.setPushToken ` method, which registers the push token and current authorization state
420512via the [ Create Client Push Token API] ( https://developers.klaviyo.com/en/reference/create_client_push_token ) .
421- The SDK's ` KlaviyoPushService ` will automatically receive * new* push tokens via the ` onNewToken ` method.
422- We also recommend retrieving the latest token value on app startup and registering it with the Klaviyo SDK.
513+ ` KlaviyoPushService ` forwards ** newly generated or rotated** tokens to Klaviyo via its
514+ ` onNewToken ` method — but only when it is your registered FCM service. If your app supplies its
515+ own ` FirebaseMessagingService ` , call ` Klaviyo.setPushToken() ` from your own ` onNewToken() ` (see
516+ [ Advanced Setup] ( #advanced-setup ) ), or rely on the startup fetch below. Note that ` onNewToken `
517+ only fires when FCM * generates or rotates* a token — it does ** not** fire for a token that
518+ already existed before the SDK was integrated, and it does not fire when FCM auto-init is
519+ disabled. For that reason, we recommend retrieving the latest token value on app startup and
520+ registering it with the Klaviyo SDK.
423521Add the following to your application or main activity's ` .onCreate() ` method:
424522
425523<details open >
@@ -464,29 +562,29 @@ if you are only using the SDK for push notifications and not analytics.
464562 and the best user experience in the context of your application. The linked resources
465563 provide code examples for requesting permission and handling the user's response.
466564
467- #### Push tokens and multiple profiles
565+ ##### Push tokens and multiple profiles
468566Push tokens are automatically associated with new profiles when you call ` setProfile ` or ` resetProfile ` .
469567No additional action is required.
470568
471- ### Receiving Push Notifications
569+ #### Receiving Push Notifications
472570` KlaviyoPushService ` will handle displaying all notifications via the ` onMessageReceived ` method regardless of
473571whether the app is in the foreground or background. You can send test notifications to a specific token using
474572the [ push notification preview] ( https://help.klaviyo.com/hc/en-us/articles/18011985278875 ) feature in order
475573to test your integration. If you wish to customize how notifications are displayed, see [ Advanced Setup] ( #advanced-setup ) .
476574
477- #### Rich Push
575+ ##### Rich Push
478576[ Rich Push] ( https://help.klaviyo.com/hc/en-us/articles/16917302437275 ) is the ability to add images to
479577push notification messages. No additional setup is needed to support rich push. Downloading the image and
480578attaching it to the notification is handled within ` KlaviyoPushService ` . If an image fails to download
481579(e.g. if the device has a poor network connection) the notification will be displayed without an image
482580after the download times out.
483581
484- #### Push Action Buttons
582+ ##### Push Action Buttons
485583[ Push Action Buttons] ( https://help.klaviyo.com/hc/en-us/article/46285872166683 ) provide the ability to add clickable buttons to
486584push notification messages. These buttons can show custom text, and, when clicked, deep link or open your app.
487585A notification can include up to 3 buttons. No additional SDK setup is required.
488586
489- #### Tracking Open Events
587+ ##### Tracking Open Events
490588To track push notification opens, you must call ` Klaviyo.handlePush(intent) ` when your app is launched from an intent.
491589This method will check if the app was opened from a notification originating from Klaviyo and if so, create an
492590` Opened Push ` event with required message tracking parameters. For example:
@@ -547,7 +645,7 @@ This method will check if the app was opened from a notification originating fro
547645app's launch intent for a tapped notification. Adjust this example to your use-case, ensuring that
548646` Klaviyo.handlePush(intent) ` is called whenever your app is opened from a notification.
549647
550- #### Silent Push Notifications
648+ ##### Silent Push Notifications
551649Silent push notifications (also known as background pushes) allow your app to receive payloads from Klaviyo without
552650displaying a visible alert to the user. These are typically used to trigger background behavior, such as displaying
553651content, personalizing the app interface, or downloading new information from a server. Silent push notifications
@@ -556,7 +654,7 @@ extension properties, where a Klaviyo message is a silent push if `RemoteMessage
556654` RemoteMessage.isKlaviyoNotification ` is ` false ` . See ` Custom Data ` and ` Advanced Setup ` sections below for
557655additional information and setup examples.
558656
559- #### Custom Data
657+ ##### Custom Data
560658Klaviyo messages can also include key-value pairs (custom data) for both standard and silent push notifications.
561659You can access these key-value pairs using the extension property ` RemoteMessage.keyValuePairs ` and check for their
562660presence with the boolean extension property ` RemoteMessage.hasKlaviyoKeyValuePairs ` . This enables you to extract
0 commit comments