Skip to main content
GUIDE · KLAVIYO9 min read

Klaviyo + TrackLayer: server-side event sync for email automation

A production guide for sending events from TrackLayer to Klaviyo as metric events, with stable profile identity, clean ecommerce properties, list subscription handling, deduplication against native web tracking, flow trigger design, testing, and migration back-fills.

Context

Why sync to Klaviyo server-side

Klaviyo is only as useful as the events that arrive in time to trigger flows. If the browser is the only source of truth, the most valuable moments are also the easiest to lose. Ad blockers can block Klaviyo's client-side pixel, privacy extensions can suppress onsite tracking, Safari can shorten browser state, and checkout redirects can detach a cart or order from the original session. The result is not just weaker reporting. It is lost flow triggers, delayed abandon-cart messages, missing browse abandonment entries, and purchase automations that fire late or not at all.

A TrackLayer server-side sync uses backend events as the source of truth. Cart, checkout, purchase, lead, subscription, refund, and product events can move to Klaviyo after your application has confirmed the action. That makes lifecycle automation less dependent on a fragile page script while still giving marketers the Klaviyo metrics and profile properties they already use.

Requirements

Prerequisites

01

A Klaviyo account with permission to create private API keys, read metrics, inspect profiles, and validate flow triggers.

02

A Private API key from Klaviyo Account → Settings → API Keys, stored as a server secret and never exposed in browser JavaScript.

03

The list_id for the main newsletter list used by your Welcome series, consent checks, and subscription reporting.

04

An event schema mapping decided before implementation, including canonical TrackLayer event names, Klaviyo metric names, required properties, consent rules, and dedup keys.

Build

Step-by-step setup

Step 1

Create the event sender

Send TrackLayer events to Klaviyo from your backend or event worker, not from the browser. The events endpoint accepts metric events that can appear in customer timelines and trigger flows. Use the private key in the Authorization header, include the current Klaviyo API revision used by your account, and log the response body because validation errors are specific enough to fix quickly.

POST https://a.klaviyo.com/api/events
Authorization: Klaviyo-API-Key pk_live_xxxxxxxxx
Content-Type: application/json
revision: 2026-04-15

{
  "data": {
    "type": "event",
    "attributes": {
      "metric": { "data": { "type": "metric", "attributes": { "name": "Added to Cart" } } },
      "profile": { "data": { "type": "profile", "attributes": { "email": "ava@example.com" } } },
      "properties": {
        "event_id": "cart_10492_add_1",
        "source": "tracklayer",
        "currency": "EUR",
        "value": 89.95
      },
      "time": "2026-04-23T10:15:30Z"
    }
  }
}
Step 2

Build the required payload contract

Treat the Klaviyo payload as an explicit contract between TrackLayer and lifecycle marketing. The required shape is data.type set to event, attributes.profile.email, attributes.properties with the business fields your flows need, attributes.metric.name, and attributes.time. Put flow conditions on stable properties, not on incidental labels from the website.

{
  "data": {
    "type": "event",
    "attributes": {
      "profile": {
        "data": {
          "type": "profile",
          "attributes": { "email": "ava@example.com" }
        }
      },
      "metric": {
        "data": {
          "type": "metric",
          "attributes": { "name": "Placed Order" }
        }
      },
      "properties": {
        "event_id": "ord_10492_purchase",
        "order_id": "10492",
        "value": 129.95,
        "currency": "EUR",
        "items": ["SKU-481", "SKU-812"],
        "checkout_url": "https://shop.example/orders/10492"
      },
      "time": "2026-04-23T10:20:00Z"
    }
  }
}
Step 3

Create or update profiles before sending lifecycle events

Klaviyo can resolve profiles during event creation, but many teams create or update the profile first so marketing properties are fresh before flows evaluate. Use POST /api/profiles when TrackLayer receives email, phone, customer ID, locale, country, predicted preference, or acquisition source. Keep this profile update small and deterministic.

POST https://a.klaviyo.com/api/profiles
Authorization: Klaviyo-API-Key pk_live_xxxxxxxxx
Content-Type: application/json
revision: 2026-04-15

{
  "data": {
    "type": "profile",
    "attributes": {
      "email": "ava@example.com",
      "phone_number": "+4915112345678",
      "external_id": "cust_34982",
      "properties": {
        "tracklayer_customer_id": "cust_34982",
        "last_source": "paid_social",
        "preferred_category": "skincare"
      }
    }
  }
}
Step 4

Subscribe the profile to the newsletter list

Metric events and list subscriptions are different jobs. A sign_up event can trigger analytics and segmentation, but the newsletter list relationship is what places a profile into your main list. Use POST /api/list-relationships with the list_id you selected in the prerequisites, and only run this route when your consent policy permits subscription.

POST https://a.klaviyo.com/api/list-relationships
Authorization: Klaviyo-API-Key pk_live_xxxxxxxxx
Content-Type: application/json
revision: 2026-04-15

{
  "data": {
    "type": "list-relationship",
    "attributes": {
      "list_id": "Y6nRLr",
      "profile": {
        "email": "ava@example.com",
        "external_id": "cust_34982"
      },
      "consented_at": "2026-04-23T10:18:00Z",
      "source": "tracklayer_signup"
    }
  }
}
Step 5

Back-fill migrations with bulk jobs

When migrating from another customer data pipeline, do not replay months of historical events through the live single-event endpoint. Use /api/events-bulk-create-jobs for controlled batches, preserve original timestamps, and tag migrated events with a property such as migration_id so marketers can exclude them from live flows if needed.

POST https://a.klaviyo.com/api/events-bulk-create-jobs
Authorization: Klaviyo-API-Key pk_live_xxxxxxxxx
Content-Type: application/json
revision: 2026-04-15

{
  "data": {
    "type": "events-bulk-create-job",
    "attributes": {
      "events": [
        {
          "type": "event",
          "attributes": {
            "metric": { "name": "Placed Order" },
            "profile": { "email": "ava@example.com" },
            "properties": {
              "event_id": "legacy_ord_7781",
              "order_id": "7781",
              "value": 74.50,
              "currency": "EUR",
              "migration_id": "spring_2026_import"
            },
            "time": "2025-11-20T13:12:00Z"
          }
        }
      ]
    }
  }
}
Schema

Event mapping

Klaviyo metrics should read like marketing actions, while TrackLayer events should remain canonical and destination-neutral. Keep the mapping table in code or configuration, and version it when marketers add new flow branches. The right-hand properties are examples of the fields that usually become Klaviyo flow filters, email personalization tokens, and segment criteria.

TrackLayer canonical eventKlaviyo metric nameTypical properties
purchasePlaced Orderorder_id, value, currency, items, discount_code, shipping_country
add_to_cartAdded to Cartcart_id, product_id, sku, product_name, value, checkout_url
sign_upSubscribed to Listlist_id, source, consented_at, signup_form, campaign
view_contentViewed Productproduct_id, sku, product_name, category, price, product_url
begin_checkoutStarted Checkoutcheckout_id, checkout_url, value, currency, item_count
searchSearched Sitequery, result_count, category, source_page
leadSubmitted Lead Formform_id, source, interest, consent_state, landing_page
refundRefunded Orderorder_id, refund_value, currency, reason, items
Deduplication

Dedup with Klaviyo native web tracking

Some teams keep Klaviyo's client-side tracker for onsite behavior while TrackLayer sends backend-confirmed events. That is a valid setup, but only if both paths agree on which events they own. Let the browser tracker keep low-risk browsing events if you need immediate onsite personalization, then let TrackLayer own checkout, purchase, subscription, refund, and lead events. If both paths can emit the same action, include the same event_id property and build flow filters that ignore duplicate source combinations.

The practical rule is simple: one user action gets one business event. A button click can create a browser hint, but the cart service should create the authoritative Added to Cart event. A thank-you page can render fast, but the order service should create the authoritative Placed Order event. Keep source set to tracklayer on server events so Metric Activity makes the path visible during debugging.

{
  "metric": "Placed Order",
  "profile_email": "ava@example.com",
  "properties": {
    "event_id": "ord_10492_purchase",
    "source": "tracklayer",
    "dedup_scope": "order",
    "order_id": "10492"
  }
}
Automation

Flow triggers

Server-side Klaviyo metrics are most valuable when they unlock automations that depend on reliable timing. Abandon cart should start when the backend knows the cart exists and the checkout URL is recoverable. Welcome series should start only after the profile is subscribed to the intended list. Post-purchase flows should use completed order truth, not a page view that may fire before the payment provider confirms the order.

Abandon cart

Powered by TrackLayer events with stable profile identity, original event time, and the properties Klaviyo needs for filtering and personalization.

Welcome series

Powered by TrackLayer events with stable profile identity, original event time, and the properties Klaviyo needs for filtering and personalization.

Back-in-stock

Powered by TrackLayer events with stable profile identity, original event time, and the properties Klaviyo needs for filtering and personalization.

Post-purchase upsell

Powered by TrackLayer events with stable profile identity, original event time, and the properties Klaviyo needs for filtering and personalization.

Browse abandonment

Powered by TrackLayer events with stable profile identity, original event time, and the properties Klaviyo needs for filtering and personalization.

Cart-to-lead

Powered by TrackLayer events with stable profile identity, original event time, and the properties Klaviyo needs for filtering and personalization.

Winback

Powered by TrackLayer events with stable profile identity, original event time, and the properties Klaviyo needs for filtering and personalization.

Validation

Testing in Metric Activity

1

Send one controlled test event

Trigger one TrackLayer event for a known test email, then open Klaviyo and confirm the metric appears in the profile timeline and Metric Activity feed with the expected timestamp.

2

Inspect properties before activating flows

Open the event detail and verify order_id, event_id, value, currency, product IDs, checkout URL, source, and consent fields. Flow filters should reference these exact property names.

3

Run a live flow dry run

Place the test profile into a draft flow, confirm the metric trigger qualifies once, and check that suppression, list membership, and conditional splits behave the same as production logic.

Diagnostics

Troubleshooting

429 rate limit

Throttle by destination, batch back-fill traffic, and retry with exponential backoff. Never convert rate-limited retries into new event IDs.

invalid_api_key

Confirm the private key is active, copied without whitespace, scoped for the account you are testing, and loaded from the server environment rather than a browser bundle.

duplicate_event warnings

Use a stable event_id per user action and keep it identical across TrackLayer retries, browser tracking, webhook retries, and migration jobs.

profile_not_found

Create or update the profile first with POST /api/profiles, then send the metric event with the same email or external_id used by the profile record.

timestamp_in_future

Send ISO timestamps from the original event moment, synchronize server clocks, and avoid using queue processing time when replaying historical events.

FAQ

Common questions

Can TrackLayer replace Klaviyo's onsite JavaScript?

For metric delivery, often yes. For onsite forms, product recommendations, and Klaviyo-specific web behavior, you may still keep Klaviyo's script. The server sync is about making the events that drive flows more reliable.

Should purchase events use Klaviyo's standard metric names?

Yes when possible. Names such as Placed Order, Added to Cart, Started Checkout, and Viewed Product match how lifecycle marketers already think about Klaviyo flows and reports.

Do I need to hash emails before sending to Klaviyo?

No. Klaviyo profiles use email as a primary identifier. Keep the private API route server-side, send the email over HTTPS, and apply your consent and retention policies before dispatch.

Will historical back-fills trigger old flows?

They can if you send them as normal live events. Use bulk jobs, preserve original timestamps, include a migration property, and add flow filters that exclude migration traffic during the import.

Where should dedup live?

Generate the event_id at TrackLayer collection time and carry it through every destination. Klaviyo, web tracking, webhooks, retries, and back-fill jobs should all receive the same ID for the same user action.

Next reads

Related implementation guides

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.

We use essential cookies to keep the site secure and functional. Analytics and third-party tags run only with your consent. See our Cookie Policy.