Klaviyo helps businesses better understand and communicate with their customers. To do that though, we need data.
This guide covers how to send data into Klaviyo through a custom integration using Klaviyo's newest generation of APIs. This information is most important for enterprise clients with their own web servers and for smaller businesses that operate on platforms without a pre-built Klaviyo integration.
If your business operates on a major ecommerce platform (e.g. Shopify, WooCommerce), the task of sending your data into Klaviyo is already handled for you. However, if your business has its own systems outside these platforms, then this guide is for you.
This functionality is called /track
and /identify
in Klaviyo's legacy APIs and /client
in the new generation.
Regardless of what they are called, this type of API request can be copied and pasted directly into your website's frontend. Custom integrations use these endpoints to push event data into Klaviyo based on customers' actions (e.g. when a customer views a product, or adds an item to a cart).
This type of information can be used for a variety of purposes. For example, developers could use this data to trigger high value flows like abandon cart nudges or to update customer profiles.
To understand client-side API calls, we'll first cover API keys for your Klaviyo account.
Klaviyo accounts have two types of API keys:
You can think of a public API key to your Klaviyo account like a username. It is a unique identifier for your business. It does not need to be a secret, which means that it can exist in your website's frontend.
A private API key, on the other hand, is like a password. It is something that should not exist in your website's code for anyone to be able to inspect and see. For API calls requesting or manipulating important information (e.g. customer personal identifiable information), Klaviyo requires a private API key.
Client-side API calls are a subset of functionality that only require a public API key to authenticate. They are less permissioned, but usually easier to integrate into your systems.
Client-side requests have a limited scope in order to prevent abuse of Klaviyo's APIs. To get information on account metrics or customer profiles, developers need to authenticate with a private key.
See here for more information on managing your account's API keys. If you believe a private API key has ever been accidentally exposed, Klaviyo recommends deleting the key and generating a new one. If you are having issues, please reach out to Klaviyo's account support and we will do our best to help you out.
For the best user experience reading this guide, please view it on NBViewer rather than natively in Github. Interacting with the guide on NBviewer cuts down on 404 errors when clicking internal links and better formats long code printouts.
You can find Klaviyo's API guides on NBViewer here.
The steps listed above are needed if you want to execute the code snippets shown in this guide. Those who are mainly interested to learn how Klaviyo's APIs work should be able to get the information without needing to run the notebook.
It is not strictly necessary to have a sandbox account with fake customer data in order to run this notebook. However, developers who are testing new functionalities should strongly consider it. Especially for use cases where you upload or change customer data, you want to make sure that you are not negatively impacting the data you have on your customers.
If you haven't worked with SDKs before (Software Development Kits), think of an SDK like a small library specific to a set of API endpoints.
Klaviyo's SDKs make working with our APIs easier by providing one-line methods for common tasks (e.g. how to update a customer's profile, change subscription status, etc.).
This walkthrough will make use of the Python language and Klaviyo's Python SDK. Klaviyo has released SDKs in Node
, PHP
, Python
, and Ruby
. Developers can find more information about Klaviyo's SDKs here.
If you are using one of those languages, Klaviyo highly recommends that you use our SDKs to make API requests. The reason being that these SDKs will perform a lot of best practices automatically under the hood (e.g. retry logic).
If you want to fully customize every part of your usage of our APIs, you are always free to make the calls directly (e.g. through HTTP requests).
This guide covers both direct API requests and requests sent through Klaviyo's SDKs.
This tutorial assumes that Klaviyo's SDK is already set up locally. To check out how this is done, select the SDK version and language you want and follow the instructions given on the SDK github. For reference, you can download the SDK with a pip install
call like the one commented out below.
Setting up the SDK locally in your codebase is most important for frequent API users and/or developers setting up a production job. Developers who are just testing Klaviyo's API capabilities can start with direct HTTP requests on Klaviyo's endpoints.
The code below imports the SDK Client along with some other helpful libraries.
# you may need to pip install the SDK for Klaviyo's current generation of APIs
# pip install klaviyo-api
from klaviyo_api import KlaviyoAPI
import json
import requests
# Note: You need to provide an API key to instantiate an SDK Client. Since we are using client-side APIs,
# we do not need a private key. Feel free to instantiate with an empty string as shown below.
klaviyo = KlaviyoAPI('', max_delay=60, max_retries=3)
To execute the code in this notebook, you will first have to specify your account's public API key. Your account's public key can be found in account settings.
Again, for developers who are testing new functionalities, you should consider using a sandbox account filled with fake customer data.
# TODO: Replace this with your Account Public Key. This is needed to run code blocks below.
public_key = 'PUBLIC_API_KEY'
Using Klaviyo's SDK, event data is passed as a dictionary object. However, if you are using CURL or HTTP to request endpoints directly, then you will need to format payloads as JSON strings
(an example is shown below).
You can take a look at the structure that payloads need to follow in Klaviyo's API documentation.
For the time being, the most important attributes to understand are profile and metric name. These are broken down in the sections below.
profile
attribute?¶An event applies to a single customer profile. Therefore, when uploading an event to Klaviyo, you need to specify the customer profile involved. You do this by providing a unique identifier for the relevant profile.
Developers need to supply this information in the profile
field. The field should map to a dictionary
Example valid profile
fields:
'profile': {'email': string}
'profile': {'$phone_number': string}
'profile': {'$id': string}
Klaviyo recommends always using email
as your profile identifier unless your business only uses Klaviyo for SMS marketing. Email is typically a more stable field that will be filled out in almost all of your customer profiles.
Developers who want to use their own id system should write these ids into the external_id field. Customer profiles start with this field blank, but the field can house any string identifier. External ids are managed by you and not Klaviyo, so if you choose to use the field as an identifier there is an additional responsibility to make sure each profile has an id and that they are unique.
Metric Name
attribute?¶Metrics in your account are essentially event types. For example, a Viewed Product event is an instance of the Viewed Product metric.
When posting an event, developers need to specify what metric the event falls into. Developers do this with the following:
'metric': {'name': string}
If you supply a metric name that already exists in your account, the uploaded event will appear alongside those prior events. If you supply a metric name that does not exist currently in your account (e.g. Hello World), one will be created with that name. Klaviyo accounts are limited to 200 metrics per account.
If you have multiple integrations sending data into your Klaviyo account, then some metric names may appear duplicated. For more information on why this happens, please see below
The code block below shows how to accomplish the same API call as below with a SDK request. It leads to the same results as a HTTP example below.
######## Reminders ########
# Always keep "type" equal to "event"
# time should be formatted as a UTC string
# properties defines the core event attributes. You do not need to provide a schema.
hello_world_payload_as_dict = {'data':
{
"type": "event",
"attributes":
{
"profile": {
'email': 'julie.rodriguez@klaviyo-demo.com'
},
"metric": {
"name": 'Hello World'
},
"properties": {'Field_1': 'True',
'Field_2': '20',
'Field_3': 'string'
},
"time": '2022-09-20T14:33:49+00:00'
}
}
}
klaviyo.Client.create_client_event(public_key, hello_world_payload_as_dict)
The code block below shows how to accomplish the same API call as above with a direct HTTP request. It leads to the same results as a SDK example above.
# The headers for a direct call on the endpoint should look similar to this (with an updated revision date)
headers = {
'Content-Type': "application/json",
'revision': "2022-10-17"
}
# move from a dictionary to a json
hello_world_payload_as_json = json.dumps(hello_world_payload_as_dict)
# specify the endpoint you want to hit
url = "https://a.klaviyo.com/client/events/"
# execute the request
response = requests.request("POST",
url,
data=hello_world_payload_as_json,
headers=headers,
params={"company_id": public_key})
print(response)
print(response.reason)
print(response.text)
<Response [202]> Accepted
After you've run the code block, the event now appears under Julie Rodriguez's profile. The screen below was generated by going into the Profiles tab, then selecting the new Hello World metric under the dropdown menu.
Now that we have covered client-side events at a high level, it is time to explore specific ways that developers use this functionality.
A core task for developers getting set up with Klaviyo is setting up an integration between what is happening on their website and their customer data living in Klaviyo. This is critically important to make sure that events like product orders are quickly and accurately reflected in your Klaviyo data. That type of event data is critical not only for sending follow-up communications, but also to secure future orders by better catering your messaging to your customers' tastes.
If your site is hosted through a major ecommerce platform (e.g. Shopify, WooCommerce, etc.), then this task is already done for you through Klaviyo's pre-built integrations with these platforms. Take a look at Klaviyo's full catalog of integrations.
If you have an online presence outside of those platforms, you may need to set up a custom integration. This is a common task for devs working to integrate larger brands into Klaviyo's ecosystem.
Since this is such a common task for developers, the developer experience team strives to make this as easy as we can. The most common way that devs choose to integrate with Klaviyo is through our JavaScript SDK. This is because of how JS can natively be embedded into websites' frontend.
This guide will cover creating and uploading event data using Python
and not JavaScript
. This is to make sure that the concepts covered in this guide are accessible to as many developers as possible.
Developers interested in running API requests in other languages should look through Klaviyo's API documentation. It has examples of how to make direct API calls on each of Klaviyo's endpoints in a number of frameworks including (JavaScript
, Node
, Python
, Java
, PHP
, and Shell
among others).
You can also find code snippets using the SDKs in other languages in our SDK documentation. For example, take a look at some common use cases with Klaviyo's JS SDK.
The code below shows an example of how to define a Viewed Product event. In this case, Julie Rodriguez viewed a copy of Moby dict
.
The dictionary describing the event, along with the company's public key, are passed to the create_client_event
which uploads the event into the Klaviyo account and links it to Julie's customer profile.
# Note: Make sure uploaded events follow the style covered here:
# https://developers.klaviyo.com/en/docs/guide-to-integrating-a-platform-without-a-pre-built-klaviyo-integration
# TODO: replace with a customer email you want this event to apply to. Consider using the sample data tool
# to generate some test accounts: https://developers.klaviyo.com/en/docs/generate-sample-data
customer_email = 'julie.rodriguez@klaviyo-demo.com'
payload_as_dict = {'data':
{
"type": "event",
"attributes":
{
"profile": {'email': customer_email},
"metric": {
"name": 'Ordered Product'
},
"properties": {'Brand': 'Harcourt Classics',
'Categories': ['Fiction', 'Classics'],
'CompareAtPrice': 19.99,
'ImageURL': 'http://www.example.com/path/to/product/image.png',
'Price': 19.99,
'ProductID': 1112,
'ProductName': 'Moby Dict',
'URL': 'http://www.example.com/path/to/product'
},
"time": '2022-08-17T14:33:49+00:00'
}
}
}
# Note: on success, the SDK will return None and the HTTP will return a 202
klaviyo.Client.create_client_event(public_key, payload_as_dict)
As we can see, our Ordered Product event for Moby dict
is now in Klaviyo. The event will now be reflected in analytics and trigger any appropriate flows.
The screen below was generated by going into the Profiles tab, then selecting the Ordered Product metric under the dropdown menu.
Developers should be aware that if they upload data into an account from multiple sources, then some metric names may appear more than once in Klaviyo (shown below). This is because Klaviyo separates events based on their source.
So, if an account uploads events both with a custom integration and through a pre-built integration, then the account will appear to have metric duplicates. The test account used in this tutorial has events uploaded through Shopify and Klaviyo's APIs.
Events uploaded from different sources sometimes have different column names or data types. Klaviyo separates these metrics by default to help keep your data clean. Multiple integrations of the same type (e.g. multiple API integrations) will be grouped into the same bucket.
Klaviyo recommends developers keep metric names consistent regardless of the source (e.g. Ordered Product should not become Ordered Product (From Website)).
Klaviyo users of accounts with multiple integrations should be aware that their data is separated by source. Users who aren't aware of this nuance risk incomplete analytics and untriggered flows.