# Klaviyo (/docs/plugins/klaviyo)



<!-- Generated from the Klaviyo plugin's manifest by scripts/docs-plugins.mjs. -->

## What it does [#what-it-does]

* **Connection.** A project connects to Klaviyo once per environment, through Klaviyo's own sign-in and consent, with the settings below.
* **Destination.** Domino syncs its members' data and the events below to Klaviyo. A destination syncs data only: it never sends messages or campaigns from your Klaviyo account.

## Connect it [#connect-it]

Each environment has its own connection, and a promotion never copies it. Anyone with read access sees its status; connecting, editing and disconnecting need publish permission.

* **Console.** On **Integrations**, the **Klaviyo** card: **Connect with Klaviyo**, fill in the settings, and grant Domino access at Klaviyo, which sends you back to Console. **Edit** changes the settings; **Disconnect** revokes Domino's access at Klaviyo and deletes it.
* **CLI.** `domino connections authorize klaviyo --config-json '{}'` prints an `authorizationUrl`. Open it within ten minutes and grant access; the connection is ready when Klaviyo sends you back. It works once.

Domino asks Klaviyo for `profiles:read`, `profiles:write`, `events:write`, `lists:read`, `lists:write`, `subscriptions:write`. Domino keeps Klaviyo's tokens sealed, refreshes them before they expire, and never shows them. If Klaviyo stops accepting them, for example because someone removed Domino's access in Klaviyo, the connection needs attention with a `reconnectReason`: **Reconnect** on the card, or `domino connections authorize klaviyo` again, restores it with the same settings.

The card shows **Not configured** when this Domino deployment doesn't have its Klaviyo app yet; nothing can connect Klaviyo until it does.

### Dry run in test [#dry-run-in-test]

In the test environment Klaviyo can run as a dry run, without a Klaviyo account: **Connect as dry run** on the card, or `domino connections connect klaviyo --dry-run --config-json '{}'`. Domino then sends nothing to Klaviyo. It records each request it would have sent, with the member it is about, and keeps the latest 500: the card's **Dry-run log**, or `domino connections log klaviyo`. Connecting a Klaviyo account in test, such as a separate test account, turns the dry run off and starts the sync again. Live has no dry run.

## Settings [#settings]

| Setting                 | Accepts                     | Required | Description                                                                                                                                                                   |
| ----------------------- | --------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `listId`                | Text, at most 64 characters | No       | List ID: The Klaviyo list to subscribe consenting members into, from the list's settings in Klaviyo. Without one, Klaviyo's account default opt-in applies.                   |
| `includeWithoutConsent` | Yes or no                   | No       | Include members without consent: Also send the profiles, properties and events of members with a verified email who haven't granted email consent. They are never subscribed. |

Relay refuses any other setting, with 422 `invalid-config` naming it in `path`.

## Events [#events]

Klaviyo receives these events, each as a [webhook](/docs/reference/webhooks) receives it, from when the connection is made:

* `attempt.rejected`
* `entitlement.granted`
* `reward.delivery.updated`
* `completion.created`
* `points.awarded`
* `review.pending`
* `reward.delivery.failed`
* `entitlement.collected`
* `referral.qualified`

## Sync status [#sync-status]

The card and `domino connections activity klaviyo` show when Klaviyo last synced, how many members were synced and how many were skipped and why, the latest backfill or resync with its progress, and the latest 20 errors with Klaviyo's answer.

Connecting sends every member's profile and attributes to Klaviyo, in pages; events go only from the connection on, so old completions set nothing off. **Resync**, or `domino connections resync klaviyo`, sends every member's profile and attributes again, never past events, to repair anything that drifted. One runs at a time.

After 10 failed deliveries in a row, or a day of failing deliveries without one success, the connection needs attention with the latest error. It keeps retrying, and the next delivery Klaviyo accepts sets it back to ready; a resync then fills anything missed.

## Reference [#reference]

### What Domino sends to Klaviyo [#what-domino-sends-to-klaviyo]

Domino never sends messages. It keeps Klaviyo profiles current and records events on them; your Klaviyo flows decide who hears what, and send it.

Members are matched on their verified email, the only key Klaviyo merges on besides phone. A member without one is skipped and counted. Without email consent a member is skipped too, unless the connection sets **Include members without consent**; those members are never subscribed.

### Profile properties [#profile-properties]

| Property                    | Value                                                                          |
| --------------------------- | ------------------------------------------------------------------------------ |
| `external_id`               | The member's first linked app identity (`app:…`): your user ID                 |
| `domino_member_id`          | The member's Relay member ID                                                   |
| `domino_user_id`            | Your user ID, as `external_id`, when the member linked one                     |
| `domino_points_<ledger>`    | The balance in each point ledger, by its key (or ID)                           |
| `domino_rank_<leaderboard>` | The rank on each active leaderboard, by its key (or ID); empty without a score |
| `domino_quests_completed`   | Quest completions that count                                                   |
| `domino_unredeemed_rewards` | Rewards earned and not collected yet                                           |
| `domino_campaigns`          | The IDs of the campaigns the member is enrolled in                             |

Ledger and leaderboard keys are lowercased, and any run of characters other than `a-z`, `0-9` and `_` becomes `_`.

### Subscriptions [#subscriptions]

A member who granted email consent is subscribed to email marketing, into the connection's list when it sets one. Withdrawing consent unsubscribes them. Connecting backfills existing members' profiles and subscriptions with the time each member consented. Domino never subscribes someone Klaviyo already has unsubscribed or suppressed on the strength of consent they gave before the connection was made, since subscribing would lift that: they stay unsubscribed until they opt in again in your app.

### Metrics [#metrics]

Events published after the connection was made are recorded on the member's profile; a referral's event is also recorded on the inviter's. Each carries the Domino event's data plus `domino_event_type` and `domino_role` (`member` or `inviter`). Connecting never replays older events.

| Domino event              | Klaviyo metric                 |
| ------------------------- | ------------------------------ |
| `attempt.rejected`        | Domino Attempt Rejected        |
| `entitlement.granted`     | Domino Reward Earned           |
| `reward.delivery.updated` | Domino Reward Delivery Updated |
| `completion.created`      | Domino Quest Completed         |
| `points.awarded`          | Domino Points Awarded          |
| `review.pending`          | Domino Review Pending          |
| `reward.delivery.failed`  | Domino Reward Delivery Failed  |
| `entitlement.collected`   | Domino Reward Redeemed         |
| `referral.qualified`      | Domino Referral Qualified      |
