Email Platform Integration
Connect GA4 with email marketing platforms (Klaviyo, Mailchimp) for email attribution, campaign analytics, and customer journey tracking.
Why Integrate Email with Analytics?
Key Benefits
| Benefit | Description | |---------|-------------| | Email attribution | Track revenue from email campaigns | | Customer journey | See pre/post email behavior | | Segment sync | Use GA4 audiences in email | | Lifecycle tracking | Email engagement + web behavior | | ROI measurement | True email channel value |
Email Tracking Fundamentals
UTM Parameters
Every email link should include UTM parameters:
https://yoursite.com/products?
utm_source=klaviyo
&utm_medium=email
&utm_campaign=summer_sale
&utm_content=hero_button
&utm_term=discount
Standard Naming Convention
| Parameter | Format | Example | |-----------|--------|---------| | utm_source | platform | klaviyo, mailchimp | | utm_medium | email | email | | utm_campaign | campaign_name | summer_sale_2024 | | utm_content | link_location | hero_cta, footer | | utm_term | variant/segment | vip, new_customer |
Klaviyo Integration
Setup UTM Tracking
In Klaviyo, enable automatic UTM tracking:
- Settings → UTM Tracking
- Enable for all email campaigns
- Configure default parameters:
utm_source: klaviyo
utm_medium: email
utm_campaign: {{ campaign.name|slugify }}
Event Sync to GA4
Use Klaviyo webhooks + GA4 Measurement Protocol:
// Server endpoint for Klaviyo webhooks
app.post('/klaviyo-webhook', async (req, res) => {
const event = req.body;
// Map Klaviyo events to GA4
const eventMapping = {
'Opened Email': 'email_open',
'Clicked Email': 'email_click',
'Received Email': 'email_received',
'Unsubscribed': 'email_unsubscribe'
};
const ga4Event = eventMapping[event.event_name];
if (ga4Event && event.ga_client_id) {
await fetch('https://www.google-analytics.com/mp/collect', {
method: 'POST',
body: JSON.stringify({
client_id: event.ga_client_id,
events: [{
name: ga4Event,
params: {
campaign: event.campaign_name,
email: event.$email
}
}]
})
});
}
res.status(200).send('OK');
});
Klaviyo Flow Integration
Track flow-triggered emails:
{% comment %} In Klaviyo email template {% endcomment %}
<a href="{{ item.url }}?
utm_source=klaviyo
&utm_medium=email
&utm_campaign={{ flow.name|slugify }}
&utm_content={{ event.name|slugify }}">
Shop Now
</a>
Pass GA4 Client ID to Klaviyo
Capture GA4 client_id when users subscribe:
// On email signup
document.querySelector('#newsletter-form').addEventListener('submit', function(e) {
const email = document.querySelector('#email').value;
const clientId = getGA4ClientId();
// Send to Klaviyo with GA4 client_id
_learnq.push(['identify', {
'$email': email,
'ga_client_id': clientId
}]);
});
Mailchimp Integration
UTM Configuration
In Mailchimp campaign settings:
- Settings → Campaign defaults
- Enable Google Analytics link tracking
- Or add manual UTMs in link editor
Custom UTM Tags
utm_source=mailchimp
utm_medium=email
utm_campaign=*|CAMPAIGN_UID|*
utm_content=*|PLACEMENT|*
Mailchimp API Integration
// Sync GA4 events to Mailchimp
const mailchimp = require('@mailchimp/mailchimp_marketing');
mailchimp.setConfig({
apiKey: 'YOUR_API_KEY',
server: 'us1'
});
async function updateMemberActivity(email, event) {
const listId = 'YOUR_LIST_ID';
const subscriberHash = md5(email.toLowerCase());
await mailchimp.lists.updateListMemberTags(listId, subscriberHash, {
tags: [{ name: event, status: 'active' }]
});
}
// Example: Tag based on purchase behavior
updateMemberActivity('[email protected]', 'purchased_recently');
GA4 Audience to Mailchimp
Using Segment or custom integration:
// Export GA4 BigQuery audience to Mailchimp
async function syncAudienceToMailchimp(audienceMembers) {
for (const member of audienceMembers) {
await mailchimp.lists.setListMember('list_id', md5(member.email), {
email_address: member.email,
status: 'subscribed',
merge_fields: {
SEGMENT: member.segment,
LTV: member.ltv
}
});
}
}
Email Attribution
Last-Click Attribution
Standard GA4 tracks this automatically with UTMs.
Email-Influenced Revenue
Track users who received email before purchasing:
-- BigQuery: Email-influenced purchases
WITH email_sessions AS (
SELECT
user_pseudo_id,
event_timestamp as email_session_time
FROM `project.analytics.events_*`
WHERE traffic_source.medium = 'email'
AND _TABLE_SUFFIX >= FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY))
),
purchases AS (
SELECT
user_pseudo_id,
event_timestamp as purchase_time,
(SELECT value.double_value FROM UNNEST(event_params) WHERE key = 'value') as revenue
FROM `project.analytics.events_*`
WHERE event_name = 'purchase'
AND _TABLE_SUFFIX >= FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY))
)
SELECT
COUNT(DISTINCT p.user_pseudo_id) as purchasers_with_email_touch,
SUM(p.revenue) as email_influenced_revenue
FROM purchases p
JOIN email_sessions e ON p.user_pseudo_id = e.user_pseudo_id
AND e.email_session_time < p.purchase_time
AND e.email_session_time > TIMESTAMP_SUB(TIMESTAMP_MICROS(p.purchase_time), INTERVAL 7 DAY)
View-Through Attribution
Track email opens → purchases (requires email platform integration):
// Data layer for email open tracking pixel
// In email: <img src="https://yoursite.com/email-open?campaign=xyz&user_id=123">
app.get('/email-open', async (req, res) => {
const { campaign, user_id } = req.query;
// Store in database or send to GA4
await storeEmailOpen(user_id, campaign);
// Return 1x1 transparent GIF
res.sendFile('transparent.gif');
});
Segment Sync
GA4 Audiences to Email
Create audience in GA4:
- Admin → Audiences → New audience
- Define conditions (e.g., purchasers in last 30 days)
- Export to BigQuery
Sync to email platform:
// Daily sync job
async function syncAudiences() {
// Query GA4 BigQuery export for audience members
const audienceMembers = await bigquery.query(`
SELECT DISTINCT
user_id,
user_properties.email
FROM \`project.analytics.pseudonymous_users_*\`
WHERE predicted_purchase_probability > 0.7
`);
// Sync to Klaviyo
for (const member of audienceMembers) {
await klaviyoClient.profiles.createOrUpdate({
email: member.email,
properties: {
high_purchase_intent: true
}
});
}
}
Email Segments to GA4
Pass email segments as user properties:
// On website load, check for Klaviyo profile
if (window._klOnsite && window._klOnsite.length) {
const profile = window._klOnsite[0];
if (profile && profile.segments) {
dataLayer.push({
event: 'set_user_properties',
user_properties: {
email_segment: profile.segments[0],
email_subscriber: true,
klaviyo_id: profile.id
}
});
}
}
Email Campaign Analytics
GA4 Campaign Report
Navigate to Reports → Acquisition → Traffic acquisition
- Filter: medium = email
- Breakdown by: campaign, source
Custom Email Dashboard
Key metrics to track:
| Metric | Calculation | |--------|-------------| | Sessions from email | Sessions where medium = email | | Email conversion rate | Purchases / Email sessions | | Revenue per email session | Total revenue / Email sessions | | Email contribution | Email revenue / Total revenue |
BigQuery Email Report
-- Email campaign performance
SELECT
traffic_source.source,
traffic_source.medium,
traffic_source.campaign,
COUNT(DISTINCT user_pseudo_id) as users,
COUNT(DISTINCT CONCAT(user_pseudo_id, session_id)) as sessions,
COUNTIF(event_name = 'purchase') as purchases,
SUM((SELECT value.double_value FROM UNNEST(event_params) WHERE key = 'value')) as revenue,
SAFE_DIVIDE(COUNTIF(event_name = 'purchase'), COUNT(DISTINCT CONCAT(user_pseudo_id, session_id))) as conv_rate
FROM `project.analytics.events_*`,
UNNEST([
(SELECT value.int_value FROM UNNEST(event_params) WHERE key = 'ga_session_id')
]) as session_id
WHERE traffic_source.medium = 'email'
AND _TABLE_SUFFIX >= FORMAT_DATE('%Y%m%d', DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY))
GROUP BY source, medium, campaign
ORDER BY revenue DESC
Post-Purchase Email Tracking
Order Confirmation Events
// Track order confirmation email sends
dataLayer.push({
event: 'email_sent',
email_type: 'order_confirmation',
transaction_id: 'T12345',
email_platform: 'klaviyo'
});
Review Request Attribution
Track if reviews came from email requests:
// On review submission
dataLayer.push({
event: 'review_submitted',
source: getUTMParam('utm_source') || 'direct',
email_requested: sessionStorage.getItem('review_email_sent') === 'true'
});
Best Practices
Link Tracking Checklist
- [ ] All email links have UTM parameters
- [ ] Consistent naming convention documented
- [ ] Dynamic parameters for personalization
- [ ] Unsubscribe links excluded from tracking
- [ ] Deep links to product pages work correctly
Privacy Compliance
- [ ] Honor unsubscribe in analytics segments
- [ ] Don't track users who opt out
- [ ] Email hashed if stored in analytics
- [ ] Respect consent preferences
Previous: CRM Integration Next: Advertising Integration