| Audience | Data engineers, marketing operations |
| Prerequisites | A Customer Studio parent model for your people |
Export email sends, opens, and clicks from your email service provider (ESP) to your warehouse. Use this data in Customer Studio to find engaged customers, exclude inactive subscribers, and follow up based on email activity.
Why export email engagement data to your warehouse
Export email engagement data to your warehouse to use it alongside purchases, product usage, and other customer data.
With this data in your Customer Studio schema, you can:
- Build engagement-based audiences. Find customers who clicked an email link in the last 30 days.
- Exclude inactive subscribers. Identify customers who haven't clicked an email recently.
- Follow up based on engagement. Use a Hold until tile in a journey to send a follow-up when someone doesn't click within three days.
- Use engagement data in AI Decisioning. Make email engagement events available to AI Decisioning as campaign events.
Plan your export
Before choosing an export method, consider these requirements and best practices:
- Check your ESP plan. Some export methods are paid add-ons, in beta, or turned on by your ESP account team. The Access column for each ESP below shows which. Confirm access before you set up your pipeline.
- Plan for historical and new events. Some export methods only collect new events. If you need historical data, load older events before setting up ongoing exports.
- Monitor for missing data. Monitor for missing files or events, not just failed jobs. If an export stops working and your ESP no longer retains the missing events, you may not be able to recover them.
- Use clicks as a stronger engagement signal than opens. Email privacy features, such as Apple Mail Privacy Protection, can record opens even when someone hasn't read a message. A click requires someone to select a link.
- Match events to your customers. ESPs use their own identifiers, which may not match your warehouse records. When multiple profiles share an email address, matching by email alone can associate events with the wrong customer. Use your own customer IDs or Hightouch Identity Resolution to connect events to the correct customers.
Standardize engagement events
Map events from each ESP to a consistent set of columns in your warehouse or data pipeline before creating event models in Customer Studio. This lets you use the same audience filters and engagement calculations across providers. Some columns, such as event_type and customer_id, may need to be derived or populated during this process.
| Column | Description |
|---|---|
event_id | A unique identifier for each event. Use the ESP event ID when available, such as Marketo's marketoGUID or Klaviyo's uuid. |
event_type | The event type, such as sent, delivered, opened, clicked, or bounced. |
event_timestamp | When the event occurred, converted to UTC. Store the time the event was loaded separately, such as in ingested_at. |
source_user_id | The recipient's identifier in the ESP. |
customer_id | The customer identifier used in your warehouse. Don't expect the ESP to provide it. |
email | The recipient's email address. Don't rely on email alone to identify customers. |
campaign_id | The campaign identifier provided by the ESP. |
message_id | The message identifier provided by the ESP. Depending on the ESP, it can identify a message definition, a send, or a dispatch. |
message_name | The campaign, journey, or message name. |
url | The clicked URL, when available. Use it to build audiences based on clicked links. |
is_unique | Whether the ESP identifies the event as unique, when available. Some ESPs deduplicate events before you export them. |
raw_event | Optional. The original event data, which you can use to troubleshoot or remap fields. |
If your ESP doesn't provide an event ID, generate one from fields that uniquely identify the event. Make sure the ID stays the same across repeated exports so you can identify duplicates. If you combine data from multiple ESPs, include the provider in the identifier.
Choose an export method
Choose your ESP below to compare export methods, historical data availability, and field mappings.
Availability and limits vary by ESP and plan. Check the linked ESP documentation before you set up your export.
Salesforce Marketing Cloud
Both export methods use scheduled automations in Automation Studio.
Add a File Transfer activity to move exported files to your SFTP server or cloud storage. Without this step, the files stay in Marketing Cloud, even when the automation completes successfully.
| Method | Access | History | Output |
|---|---|---|---|
| Data views with SQL | Requires Automation Studio | The last six months | One CSV, shaped by your query |
| Tracking extract | Requires Automation Studio | Up to six months | A .zip with one CSV per event type you select |
Each method is a sequence of Automation Studio activities. Put each activity in its own step so that each one starts only after the previous one finishes:
- Data views: A SQL Query activity writes the events to a data extension, a Data Extract activity exports the data extension to a file, and a File Transfer activity moves the file.
- Tracking extract: A Data Extract activity with the tracking extract type creates a .zip file, and a File Transfer activity moves it. End the output file name in
.zip. Select at least the Sent, Opens, Clicks, and SendJobs outputs. The other outputs identify each send only by ID, and SendJobs adds details like the email name.
Use data views if someone on your team writes SQL and you want one file with the columns you choose. Use tracking extract to export without SQL, and plan to unzip the file and load each CSV into its own table.
Filter each run to a rolling date range that overlaps the previous run, such as the last seven days, instead of fixed dates, so no events fall between runs. Remove the duplicates from overlapping runs with event_id.
Map Marketing Cloud fields to the standard columns:
| Column | Marketing Cloud field |
|---|---|
source_user_id | SubscriberKey |
event_timestamp | EventDate, converted to UTC |
message_id | JobID |
message_name | EmailName, from _Job or SendJobs |
url | URL, on clicks only |
is_unique | IsUnique |
Before you combine Marketing Cloud events with other sources, convert EventDate to UTC. Marketing Cloud stores it in Central Standard Time and doesn't adjust it for daylight saving time.
Braze
| Method | Access | History | Output |
|---|---|---|---|
| Currents | Included with some Braze packages | From the day you turn it on | Files in Amazon S3, Google Cloud Storage, or Azure Blob Storage |
| Snowflake Data Sharing | Contact your Braze account manager | The most recent two years | Shared tables in your Snowflake account or a Braze-provided reader account |
If your warehouse is Snowflake, use Snowflake Data Sharing. There's no pipeline to maintain, and it includes two years of history. Otherwise, turn on Currents as early as you can, since its history starts the day you connect it.
If your Currents connector's credentials expire, Braze stops sending events, and after five days it drops them permanently. Renew credentials before they expire, and monitor your storage bucket for missing files.
If you don't have a Snowflake account, Braze can create a reader account for you and share your data into it. If you use a reader account, copy the shared data into your own warehouse before you join it with other customer data. A reader account can only query the shared tables.
Map Braze fields to the standard columns:
| Column | Braze field |
|---|---|
source_user_id | external_user_id |
event_timestamp | time |
campaign_id | campaign_id in Currents, CAMPAIGN_API_ID in Snowflake Data Sharing |
message_id | dispatch_id, for scheduled campaigns |
message_name | campaign_name or canvas_name |
url | url, on clicks only |
is_unique | Not provided |
A Braze campaign_id covers every send of a recurring campaign, such as a weekly newsletter. To report on each send separately, use dispatch_id for scheduled campaigns. Action-based campaigns, API-triggered campaigns, and Canvas steps get a different dispatch_id for each recipient, so you can't use it to group the recipients of one send.
Iterable
To include historical engagement, use the Export API to load older events before enabling Data Sync or Snowflake Secure Data Sharing for ongoing updates.
| Method | Access | History | Output |
|---|---|---|---|
| Export API | Included | Includes history | Files or API responses you load yourself |
| Data Sync | Contact your Iterable account team | From the day you turn it on | Databricks, BigQuery, Redshift, Amazon S3, or SFTP |
| Snowflake Secure Data Sharing | Contact your Iterable account team | From the day you turn it on | Shared tables in your Snowflake account |
For near real-time events, Iterable system webhooks send sends, opens, clicks, bounces, and other events as they happen. If you use Hightouch Events, send them to a webhook event source, which can load them into your warehouse. Webhooks only send new events, so load older events with the Export API.
Before you set up an Iterable export, check these details:
- Use your project's API host. US projects use
api.iterable.comand EU projects useapi.eu.iterable.com. Data Sync also requires you to allow an IP address for your project's region. - Check data type names. The unsubscribe data type is
emailUnSubscribe, with a capital S. - Deduplicate after a full refresh. For Amazon S3, a Data Sync full refresh adds the full dataset again without deleting existing files. Remove duplicates with
event_idto avoid double-counting events.
Map Iterable fields to the standard columns:
| Column | Iterable field |
|---|---|
source_user_id | userId or email, depending on your project. Snowflake Secure Data Sharing event tables include EMAIL. |
event_timestamp | createdAt |
campaign_id | campaignId |
message_id | messageId |
message_name | CAMPAIGN_NAME in Snowflake Secure Data Sharing, or campaign data from Data Sync |
url | url, on clicks only |
is_unique | Not documented |
Klaviyo
Data warehouse sync is part of Advanced KDP, which isn't included in Klaviyo's standard marketing plan. Without it, use the Events API for ongoing exports. The Bulk Export API is invite-only during beta, so request access from Klaviyo before you plan a backfill around it.
| Method | Access | History | Output |
|---|---|---|---|
| Events API | Included | Includes history, slow at volume | API responses you load yourself |
| Bulk Export API | Invite-only beta | Includes history | A downloaded file per export job |
| Data warehouse sync | Requires an Advanced KDP subscription | Up to all history, chosen when you connect | Hourly syncs to Snowflake, BigQuery, Redshift, Databricks, Azure Synapse, or Amazon S3 |
When you map event_type, use Klaviyo's metric names: Received Email maps to delivered, Opened Email to opened, and Clicked Email to clicked. Klaviyo records Received Email when a recipient receives an email and doesn't record a separate send event, so Klaviyo counts won't match send counts from other ESPs. Campaign Name can repeat across campaigns, so use $message to identify a specific message.
Map Klaviyo fields to the standard columns:
| Column | Klaviyo field |
|---|---|
source_user_id | profile_id |
event_timestamp | datetime |
campaign_id | No direct equivalent. Use $message for campaigns and $flow for flows. |
message_id | $message |
message_name | Campaign Name |
url | URL, on clicks only |
is_unique | Not documented |
Marketo
Both Marketo Engage export methods are APIs, so you build and maintain the integration.
| Method | Access | History | Output |
|---|---|---|---|
| Bulk Activity Extract API | Requires an API user with activity access | Includes history, in chunks of up to 31 days | A downloaded CSV per export job |
| REST API | Requires an API user with activity access | Includes history, slow at volume | API responses you load yourself |
Use the Bulk Activity Extract API for daily exports and backfills. It has a daily export quota of 500 MB, shared across leads, activities, program members, and custom objects. Exports that other teams run against the same Marketo instance count toward the same quota. Export files expire after seven days. If you reach the quota, use the REST API until the quota resets at midnight US Central Time.
Map Marketo fields to the standard columns:
| Column | Marketo field |
|---|---|
event_id | marketoGUID |
source_user_id | leadId |
event_timestamp | activityDate |
campaign_id | campaignId, the smart campaign that triggered the email |
message_id | primaryAttributeValueId, the email ID |
message_name | primaryAttributeValue, the email name |
url | In the attributes JSON, on clicks only |
is_unique | Not applicable. Marketo logs one open per lead per email. |
Marketo keeps send and delivery events for less time than open and click events, so a long backfill can include opens and clicks without their matching sends. If export jobs overlap, deduplicate on marketoGUID.
Add engagement events to Customer Studio
After loading engagement events into your warehouse, add them to your Customer Studio schema to use them in audiences and journeys.
- Connect events to customers. Join each event to your parent model using
customer_id. - Create event models. Create an event model for each event type you want to use, such as
Email Sent,Email Opened, andEmail Clicked. If you store all events in one table, filter each model byevent_type. - Set the timestamp. Select
event_timestampas the timestamp column. - Set the primary key. Select
event_idas the primary key. Event-based journeys require a primary key. - Verify your data. Filter on events to create a test audience of customers who clicked an email in the last 30 days. Compare the number of customers in the audience with the number of unique clickers your ESP reports for the same period.
Results may differ from your ESP reports because providers count events differently or exclude events associated with deleted profiles.
Next steps
- Plan your data model to decide how engagement events fit with the rest of your schema.
- Filter on events to build audiences and exclusion lists from engagement.
- Prepare data for AI Decisioning to use engagement events as campaign events for AI Decisioning agents.