Data Analysis and Reporting in Marketing
Campaign Optimization and Analytics

How to Connect Klaviyo to Google Sheets for Ecommerce Email and SMS Attribution

Adela
May 15, 2026
Klaviyo to Google Sheets: Email & SMS Attribution (2026)

If you run email or SMS for a DTC brand, Klaviyo knows what every campaign and flow drove. What it does not show cleanly is how that revenue stacks up against your paid media spend, which acquisition channels bring in subscribers worth $200 of lifetime revenue versus $20, or how your post-purchase flows perform by cohort.

This guide covers three methods to pull Klaviyo data into Google Sheets in 2026, the Klaviyo-specific gotchas at each layer, and the two ecommerce attribution dashboards that change how email and SMS reporting works: channel-level revenue attribution (Klaviyo joined to paid ads spend) and subscriber LTV by acquisition channel. The methods are means. The dashboards are the point.

For the connector layer across the rest of the marketing stack, our individual guides cover HubSpot, LinkedIn Ads, Meta Ads, GA4, and Search Console. This post extends to email and SMS, which most paid-media reporting stacks ignore until revenue stops adding up.

Where ecommerce revenue lives in Klaviyo

Before picking a method, you need to know what Klaviyo exposes and how it organizes attribution. Email and SMS revenue is computed against an attribution window set in Klaviyo Account Settings (default: 5 days for click, 1 day for open). Every revenue number you pull is window-bounded.

The core objects that matter for revenue reporting:

  • Profiles. Individual subscribers with identifiers, properties, and a full event history. The $source property captures where the profile entered Klaviyo (Shopify checkout, embed form, signup form ID, etc.). This is your acquisition-channel anchor.
  • Metrics. Klaviyo events. The two that drive revenue reporting: Placed Order (with the order value and product list as event properties) and Active on Site (browse abandonment trigger).
  • Campaigns. One-time email or SMS sends. Each has its own attributed revenue and unique open/click data.
  • Flows. Automated sequences (welcome series, abandoned cart, post-purchase, win-back). Each message in a flow has its own attributed revenue.
  • Lists and Segments. Subscriber groupings used for targeting. Useful for cohort definitions.

The revenue numbers in Klaviyo's UI are aggregated views over these objects. To get to channel-level attribution or LTV by acquisition, you need the underlying event data joined to profile properties, which means pulling rows, not just the summary cards.

Method 1: Manual CSV export from the Klaviyo UI

For one-off audits, end-of-month executive snapshots, or before you have an API budget approved. Fast, free, brittle by next week.

Setup: in Klaviyo, navigate to Analytics or the specific Campaign/Flow report, click Export, choose CSV. For campaign-level data, the campaign performance view exports include attributed revenue, recipients, opens, clicks, and unsubscribes. For profile data, exporting a list or segment includes profile properties plus event aggregates if you select those columns.

Klaviyo-specific gotchas at this layer:

  • Account-level revenue export caps at 12 months. Year-over-year reporting on email and SMS performance requires accumulating monthly exports forward into Sheets if you want longer history.
  • Flow exports are per-flow, not bulk. Want revenue across 30 flows? That's 30 manual exports. Quick for a quarterly review, painful for monthly.
  • SMS revenue is mixed into email reports by default. The breakdown by channel requires filtering by Message Channel in the report builder before export. Most teams export the combined number and assume it's email.
  • Attribution windows are not exported as a field. The number is computed inside Klaviyo's UI based on the account-level window setting. If someone changes the window, historical exports use the old number; new exports use the new number. There's no "as of" timestamp.

When this method fits: board snapshot, quarterly review, audit before reworking flows.

When it does not: any report that refreshes more than monthly, or anything joining Klaviyo data to paid media spend.

Method 2: Apps Script with the Klaviyo API

The free path for an in-house ecommerce or marketing ops team that wants daily refresh without a connector subscription. Setup is 30-60 minutes the first time, then 15-20 minutes per additional report type.

Step 1. Generate a Klaviyo Private API key. In Klaviyo: Account → Settings → API Keys → Create Private API Key. Scopes: minimum read access on the relevant objects (Profiles, Metrics, Events, Campaigns, Flows depending on what you're pulling). Store the key securely; never commit it to a public Sheet or GitHub.

Step 2. In your Sheet, open Extensions → Apps Script and paste a script along these lines:

function exportKlaviyoCampaignRevenue() {
  const KLAVIYO_KEY = 'YOUR_PRIVATE_KEY';
  const baseUrl = 'https://a.klaviyo.com/api/campaigns/';
  const headers = {
    'Authorization': 'Klaviyo-API-Key ' + KLAVIYO_KEY,
    'revision': '2024-10-15',
    'Accept': 'application/json'
  };

  const sheet = SpreadsheetApp.getActiveSheet();
  sheet.clear();
  sheet.appendRow(['Campaign ID', 'Name', 'Send Time', 'Channel', 'Recipients', 'Opens', 'Clicks', 'Attributed Revenue']);

  let nextUrl = baseUrl + '?filter=equals(messages.channel,"email")&include=campaign-messages';
  while (nextUrl) {
    const response = UrlFetchApp.fetch(nextUrl, { headers: headers, muteHttpExceptions: true });
    const data = JSON.parse(response.getContentText());
    (data.data || []).forEach(campaign => {
      // Fetch performance metrics per campaign from Reporting API
      // Append row with attributed revenue, opens, clicks
    });
    nextUrl = data.links && data.links.next ? data.links.next : null;
  }
}

The Klaviyo API documentation covers every endpoint, including the Reporting API endpoints that expose attributed revenue per campaign and flow.

Step 3. Schedule it. Apps Script → Triggers (clock icon) → Add Trigger → run your function daily before the team's check-in.

Klaviyo-specific gotchas at the API layer:

  • API revision header is mandatory. Klaviyo's API is versioned by date (revision: 2024-10-15 or a later 2025/2026 revision). Skip it and the request fails. Pin a revision; when Klaviyo deprecates it, they email you and give a migration window.
  • Rate limits are per-endpoint, not per-key. Most read endpoints support roughly 350 requests per minute steady-state (see the official rate limits documentation). Hit it and you get a 429. Build backoff retry with exponential delay.
  • Profile properties don't include event history by default. To get the $source for a profile, you fetch the profile object. To get their Placed Order history, you query the Events endpoint filtered by profile ID and metric ID. Two endpoints, joined client-side.
  • Flow-level revenue requires a different endpoint than campaign-level. Campaigns expose attribution through /api/campaign-recipient-estimations/ and reporting endpoints. Flows expose through /api/flow-action-attributions/ patterns. The two have different shapes; consolidate to a unified schema in your script before writing to Sheets.
  • SMS and email share campaigns but split metrics. Filter messages.channel to separate them. Most homegrown scripts skip this and double-count revenue when a customer received both an email and SMS for the same campaign.
  • Apps Script execution limit. Workspace Free: 6 minutes. Workspace paid: 30 minutes. Pulling 12 months of campaign-level data with profile properties can blow past 6 minutes. Solution: process by month or paginate aggressively.

The combination of those gotchas explains why teams that start with Apps Script often move to a managed connector once they have more than three Klaviyo accounts or want SMS broken out automatically.

Skip the Apps Script maintenance

Dataslayer connects Klaviyo to Google Sheets, Looker Studio, BigQuery, and Power BI on a schedule. Email and SMS broken out separately, flow-level revenue exposed, multi-account support for agencies, and pre-built fields for attribution windows.

Try Dataslayer Free

Method 3: Scheduled no-code connector

The path for ecommerce teams running multiple brand accounts (agency-style), DTC brands with high SMS volume, or anyone joining Klaviyo data to paid media spend on a schedule.

Dataslayer connects Klaviyo to Sheets via the Klaviyo Private API key flow in under 10 minutes. From Google Sheets: Extensions → Add-ons → Get add-ons → install Dataslayer. Then Extensions → Dataslayer → Launch Sidebar, choose Klaviyo, paste the private key, pick the data type (Campaigns, Flows, Profiles, Metrics, Events), pick the fields and date range, click Run.

Why a connector specifically wins for ecommerce Klaviyo reporting:

  • Multi-account ecommerce-native. Agencies managing 5-20 DTC brand Klaviyo accounts query them in one workbook with an account column. The connector batches API calls respecting per-account rate limits.
  • Email and SMS pre-split. Channel breakdown is a built-in dimension. No filter logic to remember; SMS revenue is its own row.
  • Flow-level attribution exposed natively. The Klaviyo flow-action attribution endpoints are surfaced as dimensions, not raw API responses. Welcome series revenue separates cleanly from abandoned cart from post-purchase.
  • Cross-source joins to paid media. Once your Klaviyo data lives in Sheets alongside Meta Ads and Google Ads spend, blended CAC and channel-attributed revenue are formula-distance away.

Costs: a free tier covers a single connector and user; paid tiers scale up to agencies running multiple Klaviyo accounts in one workbook. Current pricing here.

The Klaviyo gotcha that NO method fixes: attribution windows are an account-level setting, not a per-report parameter. If you change the click attribution from 5 days to 14 days in Klaviyo, every historical report you regenerate uses the new window for the lookback. The Sheet you exported last month is the only record of the old number. Snapshot regularly if window changes happen.

The 2 ecommerce dashboards worth building

Once Klaviyo data flows into Sheets (any of the 3 methods), these are the two reports that change how ecommerce email and SMS teams operate. Neither is a default Klaviyo view, and both require joining Klaviyo data to other sources or to cohort definitions.

Dashboard 1: Channel-level revenue attribution (Klaviyo + paid ads)

The question: if I cut Meta Ads spend by 30%, what happens to my email-attributed revenue? More precisely: how much of my Klaviyo-attributed revenue is incremental versus what I would have captured from paid acquisition anyway?

Columns to pull from Klaviyo:

  • Campaign or flow ID, name, channel (email/SMS)
  • Send date, attributed revenue, recipients, conversion count
  • Profile $source property aggregated to campaign level (where these recipients came from)

Columns to pull from Meta Ads (or other paid platforms):

  • Campaign ID, daily spend, conversions, purchase events
  • UTM campaign on landing pages

Calculations in Sheets:

  • Email revenue attributed to paid-acquired subscribers: SUMIFS where profile $source matches a paid channel (typically Shopify checkout with a Meta UTM, or a paid signup form)
  • Email revenue attributed to organic-acquired subscribers: SUMIFS where $source matches non-paid (organic Shopify, referral, embed form)
  • Paid CAC, blended with email: (paid spend) ÷ (new paid-acquired subscribers + first-purchase revenue from those subscribers attributed back)

Pivot layout:

  • Rows: acquisition channel (Meta, Google Ads, Organic, Referral)
  • Columns: time period (month or quarter)
  • Values: total subscriber count, total Klaviyo revenue, blended CAC
  • Conditional formatting: highlight channels where Klaviyo revenue per subscriber is below your acquisition CAC

What it surfaces that the Klaviyo UI does not:

  • Whether the $200 Meta CAC is "worth it" once you include the email LTV those subscribers generate
  • Whether organic subscribers actually drive more revenue per profile than paid (often yes for DTC)
  • Which paid signup forms drive subscribers who never open a single email

Dashboard 2: Subscriber LTV by acquisition channel

The question: of subscribers acquired in Q1, what's the average revenue per profile after 90 days, by acquisition channel? After 180 days? After a year?

Columns to pull from Klaviyo:

  • Profile ID, email, $source, $created date
  • List subscription dates
  • Placed Order events (date, value) per profile

Calculations in Sheets:

  • Cohort definition: group profiles by month of $created and by $source
  • LTV day 30 / 90 / 180 / 365: for each profile, sum Placed Order value within X days of $created
  • Average LTV per cohort: AVERAGEIFS by cohort month × source

Pivot layout:

  • Rows: cohort month (acquisition month)
  • Columns: days since acquisition (30, 90, 180, 365)
  • Values: average LTV per cohort, split by source
  • Conditional formatting: highlight cohorts where 30-day LTV is unusually high (indicates strong post-purchase flow performance) or unusually low (indicates a channel sourcing low-intent subscribers)

What this dashboard answers that the Klaviyo UI cannot:

  • Which signup forms produce subscribers who buy multiple times in 180 days
  • Whether your post-purchase flow is actually moving the needle on second-purchase rate (compare cohorts before/after a flow change)
  • Whether SMS subscribers have higher or lower LTV than email-only subscribers at the same acquisition month

Comparing the three methods

Aspect Manual CSV Apps Script Scheduled connector
Setup time 5 min 30-60 min Under 10 min
Cost Free Free From $35/mo
Email vs SMS split Manual filter Filter logic in code Native dimension
Flow-level attribution Per-flow manual Second endpoint required Surfaced natively
Scheduled refresh No Yes (Apps Script triggers) Yes (built in)
Multi-account One export per account One script per account Native, one query
Cross-source joins (paid ads) Manual Manual Same workbook, formula-distance
Code maintenance None Owner Vendor

The decision usually comes down to account count and how often the dashboard refreshes. One brand and a Sheets-fluent marketer: Apps Script. Multiple brands or daily refresh: scheduled connector. Quarterly review only: manual CSV.

Klaviyo quirks worth knowing

Five behaviors that affect every method and every dashboard you build on top of Klaviyo data:

  • Attribution windows are account-level, retroactive on regeneration. Change the click attribution from 5 to 14 days and every historical report regenerated after that uses 14 days. Snapshot revenue before window changes if you care about historical comparability.
  • Custom properties are namespaced. Klaviyo distinguishes built-in properties ($first_name, $source, $created) from custom (shopify_customer_tags, first_purchase_value). Built-ins start with $. Skip the prefix in API calls and the filter silently returns empty.
  • Profile merge changes IDs. When Klaviyo identifies that two profiles are the same person (same email after a previously anonymous browse), the older profile ID is merged out. Joining Klaviyo profile IDs to other systems requires handling occasional ID changes.
  • Active on Site requires the onsite tracking script. Without it, browse abandonment flows do not fire, and the Active on Site metric in revenue reports is empty. Verify in Klaviyo: Settings → Integrations → Web Tracking.
  • Suppressed profiles still appear in some exports. A profile suppressed (unsubscribed, bounced, marked spam) still exists; it just stops receiving messages. Cohort LTV math should typically include them since the order history is real, but campaign performance reports should filter them out of recipient counts.

Common errors and how to read them

401 unauthorized: the private API key is invalid, revoked, or you sent it without the Klaviyo-API-Key prefix in the Authorization header.

403 forbidden with scope error: the private API key was created without read scope on the object you're requesting. Edit the key in Klaviyo settings, expand scopes, save, retry.

429 too many requests: rate limit hit. Klaviyo includes a Retry-After header indicating seconds to wait. Implement exponential backoff or stagger refresh times across multiple Klaviyo accounts.

410 gone on profile fetch: the profile was deleted (GDPR data deletion request, or merged into another profile). Skip and continue; do not retry.

Empty data array with no error: the filter or date range excluded everything. Common cause: filtering by messages.channel with a typo, or pulling campaigns from a date range before the account had any sends.

FAQ

Does Klaviyo's UI show channel-attributed revenue across email and SMS by default?
The aggregate revenue card combines both. Breaking out email versus SMS requires either filtering in the reporting view (Campaign Performance → filter by Message Channel) or pulling the data via API or connector with the channel dimension. Most account-level revenue summaries default to combined.

How far back can I export Klaviyo data?
For campaign and flow performance, the account-level revenue export caps at 12 months. For profile and event data via API, history depends on your Klaviyo plan; the standard retention is well beyond 12 months for most plans. To preserve longer history, snapshot to Sheets or a warehouse forward in time.

What's the difference between Klaviyo flow attribution and campaign attribution?
Campaign attribution is per-send (one email or SMS to a list at a point in time). Flow attribution is per-message-in-an-automation (the second email in your welcome series has its own attributed revenue separate from the first). Reporting both at flow-message granularity is the only way to know which welcome step actually drove revenue.

Can I join Klaviyo data with Meta Ads data in Google Sheets without a warehouse?
Yes, if the data is in the same workbook. Pull Klaviyo to one tab and Meta Ads to another via separate connectors or scripts, then use VLOOKUP/QUERY to join on UTM campaign or by date. For more than 100K profile rows, formulas slow down; that's when a warehouse layer starts paying back.

How do I track SMS revenue separately from email?
Filter by messages.channel = "sms" in the Klaviyo API or in the connector's channel dimension. The Klaviyo UI also supports this filter in Campaign Performance and Flow Performance reports. Most homegrown scripts skip this filter and end up double-counting when a customer received both an email and an SMS for the same campaign.

Are Klaviyo Apps Script scripts limited the same way as HubSpot scripts?
Same Apps Script execution limits (6 min free Workspace, 30 min paid). Same rate limit handling pattern. The differences are at the API layer: Klaviyo uses date-versioned revisions, different filter syntax, and per-endpoint rate limits rather than account-level.

Conclusion

The three methods to pull Klaviyo into Google Sheets sit on a spectrum: manual CSV for one-off snapshots, Apps Script for free daily automation with code maintenance, scheduled connector for hands-off ecommerce reporting across multiple accounts. The right method depends on account count, refresh frequency, and whether SMS performance and flow-level attribution need to break out automatically.

But the methods are means, not the end. The two dashboards (channel-level revenue attribution and subscriber LTV by acquisition channel) are the work that changes how ecommerce email and SMS teams report results. Both require joining Klaviyo data to cohort definitions and to paid ads spend, and both have become more valuable through 2026 as DTC brands lean harder on email and SMS, which the Klaviyo UI does not surface. Build them once; reference them every week.

Pull the data. Build the dashboards. The connector is one afternoon's setup; the attribution clarity is something your founders will reference for the rest of the year. Start a free Dataslayer trial if you want to skip the API maintenance and go straight to the dashboards.

HOW CAN WE HELP?

Knowledge baseSupport ticketContact

RELATED POST

How to Connect Klaviyo to Google Sheets for Ecommerce Email and SMS Attribution

Visual Query Builder vs SQL: Which One Should Your Marketing Team Use?

BigQuery for Marketing Teams: The Hidden Costs You Won't See Until Month 3

Our Partners

Google Cloud Partner
Microsoft Partner