PPC Rebels article cover about GA4 campaign data import and non-Google ad spend in 2026

GA4 Campaign Data Import 2026: Schema, Join Keys and a ROAS You Can Trust

As long as spend lives in five ad platforms and conversions live in GA4, every ROAS conversation turns into an argument about whose spreadsheet is right. GA4 campaign data import closes that gap: you feed GA4 the daily cost, clicks and impressions of your non-Google channels, and the reports start calculating cost per click and return on ad spend for every source inside one system. In 2026 Google renamed the feature — what used to be cost data import is now campaign data import. Below: the exact file schema, the join keys, the limits, the UTM traps that quietly break everything, and an honest list of what this report will never tell you.

What GA4 campaign data import actually does

GA4 knows how many sessions and conversions arrived from utm_source=bing. It has no idea what you paid for them. The import supplies the missing half: for each source/medium pair on a given day you submit cost, clicks and impressions, and GA4 joins that to its own behavioural and revenue data.

The output is non-Google cost per click and return on non-Google ad spend inside standard reports — no exports, no manual reconciliation in a sheet.

You do not import Google Ads. Its spend flows in automatically through the account link. This feature is for everything else: paid social, native networks, push and teaser traffic, paid newsletter placements, flat-fee partnerships.

The schema: required and optional fields

Dimensions

Field Status Notes
Campaign source (utm_source) required join key
Campaign medium (utm_medium) required join key
Date required ISO 8601, YYYY-MM-DD
Campaign ID (utm_id) optional, highly recommended more stable than a campaign name
Campaign name (utm_campaign) optional, highly recommended makes reports readable
Currency required if cost is included ISO 4217 code

Metrics

At least one of three is required: Clicks, Cost, Impressions — all as daily values. Cost is submitted in the 0,000.00 format.

CSV headers

The template the uploader expects:

  • utm_id, utm_campaign, utm_source, utm_medium, date, impressions, clicks, cost

A sample row: bing_123abc | Summer_fun | bing | cpc | 2026-12-01 | 12242371 | 367271 | 36727.10.

Date constraints: later than 2013, never in the future. You can either map currency from a field in your file or hardcode it as a static value during mapping, in which case it applies to every cost value in that import.

Join keys: where this breaks

GA4 joins imported data to its own data on three fields: utm_source, utm_medium and date. The match must be exact — the documentation spells it out with the example that “Facebook” and “facebook” are not exact matches.

Two rules follow:

  • Your links and your file must carry identical values. If traffic is tagged fb/cpc and you upload facebook/cpc, the spend lands as an orphan row joined to nothing.
  • Case and separators are part of the key. Meta and meta, paid_social and paid-social are different sources.

utm_term and utm_content cannot be included in the file at all — they are fine in URLs, but the import rejects them. Inconsistent campaign naming (SpringSale vs Spring_Sale) splits one effort into two report rows. We cover building one tagging standard across the ad platform, GA4 and your CRM in UTM tagging and naming conventions.

Overwrites and re-uploads

Uploading a file with the same set of keys overwrites — it does not add. That matters: ad platforms restate yesterday’s spend after the fact (adjustments, refunds, filtered traffic), so re-uploading the last few days every day is normal practice. Reporting always uses the most recently uploaded values.

A single file cannot contain duplicate keys — each row must be unique on source + medium + date.

Where imported data shows up

  • Reports → Acquisition → Non Google campaign — the primary view.
  • Advertising → Planning → All channels — the cross-channel roll-up.
  • Reports → Data import → Campaign data import validation — the reconciliation report.

One structural detail drives everything else: the join happens at query time, not at collection. Three consequences:

  1. It works against already-processed events, so you can backfill historical spend and past periods will recalculate.
  2. Delete the import source and the data disappears from reports — nothing is baked into historical tables.
  3. Query-time data is not available when building audiences or segments in Explorations. You cannot create an audience of “users from channels where CPC exceeded X.”

Data takes up to 24 hours to appear after upload. Do not debug in the first hour.

Two health metrics worth watching

Metric Meaning
% imported share of file rows accepted. 100% means nothing was dropped
Match rate share of imported rows successfully joined to GA4 data. Computed over the most recent two years of imported data only

A subtlety worth internalising: cost, clicks and impressions are reported against any combination of the imported dimensions regardless of match rate. Even at zero matching you will see spend — it simply will not connect to user behaviour. A low match rate almost always means tagging mismatch rather than an upload failure.

Ways to deliver the data

Manual CSV upload

Fine for getting started and for low-frequency channels. The drawback is obvious: someone has to do it daily.

Scheduled SFTP

You provide a server username, a server URL, a frequency (daily, weekly, monthly) and the hour the upload starts. The server must support the ssh-rsa or ssh-dss host-key algorithms; the default port is 22. GA4 issues a public key you authorise on your side. Daily is the finest granularity available.

Warehouse and storage connectors

In open beta, and only for campaign data: Amazon Redshift, Amazon S3, BigQuery, Google Cloud Storage, Google Sheets, HTTPS, MySQL, PostgreSQL, SFTP and Snowflake. If you already maintain a spend table in a warehouse, this is the cheapest path to maintain. We explain how GA4’s own event export works and what you can compute on it in GA4 BigQuery Export for paid traffic.

Direct ad-platform connectors

GA4 supports Meta, Pinterest, Reddit, Snap and TikTok directly. They run automatically every day, with two caveats:

  • on connection the source attempts to pull 24 months of historical data into the property;
  • all paid traffic from that platform must use a single unique utm_source and a single unique utm_medium. If you are running fb/cpc, Meta/cpc and facebook/paid simultaneously, the connector will not work — use CSV, Sheets or BigQuery instead.

And a warning: if overlapping campaign data already exists from another import source, delete those datasets first or you will double-count spend.

Limits to know before you design the pipeline

Limit Value
Size per import source 1 GB
Uploads per property per day 120
Campaign data storage 1 GB across all import sources
Time until data appears up to 24 hours
Best SFTP frequency once daily

Current usage is visible through the quota information button in the interface. One more detail for larger setups: subproperties and roll-up properties do not inherit query-time widening imports, so campaign data has to be configured in each property separately.

Setup, step by step

  1. You need Editor or above at property level.
  2. Admin → Data collection and modification → Data import.
  3. Create import source, give it a name.
  4. Select the data type — campaign data.
  5. Pick the import source: manual CSV upload, SFTP, or a connector from the dropdown.
  6. Next → map your file’s fields to GA4 fields. You set currency here, either from a field or as a static value.
  7. Import.

A detail that trips people up at mapping: dynamic parameters such as {{campaign.name}} are not accepted. They are encouraged in the ad platform’s own URL settings, but they must be resolved to literal values before the file reaches GA4.

To add data to an existing source, use the import button on its row. The file must contain the same fields or a subset of them; changing the field set means deleting the source and creating a new one.

What this report will not do

  • It is not attribution. The import adds money to an existing model; it does not change how GA4 distributes conversions across channels.
  • It is not reconciliation with the ad platform. You supply the spend. A bad export produces a confident, wrong report.
  • It is not audience data. Query-time data cannot be used for segments in Explorations.
  • It does not fix conversion discrepancies. If GA4 and your ad platform count conversions differently, importing cost will not help; the causes and a diagnostic order sit in Google Ads and GA4 conversion discrepancy.
  • It does not replace measurement on site. If half your conversions are lost in the browser, accurate spend simply gives you an accurate picture of a loss; fix the floor first with Google tag gateway.

A worked example: what the report looks like

Say you upload a week of spend for three third-party channels while GA4 counts conversions and revenue on its own. The non-Google campaign report starts reading like this:

Source / medium Cost Clicks Conversions Revenue CPC ROAS
meta / cpc 4,200 5,600 128 11,900 0.75 2.83
tiktok / cpc 2,100 4,900 41 3,150 0.43 1.50
partner_mail / email 900 1,150 37 4,100 0.78 4.56

The numbers are illustrative; the reading pattern is the point. The cheapest click belongs to the worst-returning channel — invisible until the spend sits in one system, because inside TikTok’s own dashboard that campaign looks healthy on CPC and CTR. Second, the smallest budget shows the best ROAS, which usually means “this channel is capped by audience size,” not “move the entire budget here.” Third, the three rows are only comparable because one tool counted conversions and revenue under one set of rules.

Decide explicitly what counts as revenue. If GA4 receives order value at checkout, ROAS runs optimistic: refunds, cancellations and unpaid orders never reach that figure. An honest picture needs either confirmed revenue pushed from the CRM or a correction factor stated openly in the report.

Common mistakes in a GA4 campaign data import file

  • Decimal separator. Submitting 36727,10 instead of 36727.10 is the classic reason rows import fine and totals look absurd.
  • Implicit currency. If the ad platform bills in one currency and the GA4 property reports in another, and the file says nothing, the math drifts. Set the ISO code explicitly or hardcode it at mapping.
  • Tax handled inconsistently. Decide once, for every source, whether cost includes tax — otherwise cross-channel comparison is meaningless.
  • Assuming rows add up. A daily job re-uploading “yesterday” is safe because identical keys overwrite. But change utm_campaign while keeping the same source/medium pair and the campaign-level view will surprise you.
  • Platform-local dates. Ad platforms close the day in their own time zone; GA4 reports in the property’s. Invisible weekly, obvious daily.
  • Importing Google Ads anyway. That double-counts against the automatic account link.

A one-week rollout

  1. Day 1. Export the actual utm_source/utm_medium values GA4 is receiving for paid traffic. That is your reality, not what the media plan says.
  2. Day 2. Collapse tagging to one standard: one platform, one pair of values. Fix it in the ad platforms, not in old links.
  3. Day 3. Build a test CSV covering the last seven days for one channel. Check date format, currency and the decimal separator.
  4. Day 4. Upload, wait 24 hours, read % imported and match rate.
  5. Day 5. Work through mismatches in the validation report and correct the values.
  6. Days 6–7. Automate: scheduled SFTP or a warehouse connector, re-uploading the last 3–5 days daily.

Once every channel’s spend sits in one place, budget allocation becomes a conversation about numbers instead of instincts. For the Google side of the picture, keep the channel breakdown of automated campaigns next to it — see Performance Max channel reporting. And if your Q4 plan leans on discounting, the rules behind the Deal Ends annotation in Google Shopping are worth reading before you set the calendar.

Reconciling with the ad platform: what is normal

The first question after rollout is always why GA4 and the platform dashboard disagree. Here is where to expect a gap and where it signals a break.

Comparison Expected gap When it is a problem
Daily spend near zero — you supply it yourself any visible difference means a broken export or a time-zone mismatch
Clicks vs. sessions sessions always lower; some users leave before the page loads a multiple-fold gap points at landing speed or a broken tag
Platform conversions vs. GA4 conversions substantial, from different models and windows the gap widening month over month means measurement is drifting
GA4 revenue vs. CRM revenue GA4 usually higher a difference larger than your refund and cancellation rate

GA4 ships a validation report for exactly this: it shows which source/medium pairs are already arriving in the property and lets you compare imported totals against what the platform reports. Start debugging there rather than in the general reports — mismatches surface immediately and without interpretation.

Keep in mind that GA4 aggregates imported metrics daily. Hourly analysis or ad-level breakdowns are impossible on this data: the finest grain available is day, source, medium and optionally campaign.

Where PPC Rebels fits

Consolidated spend is only as useful as the campaigns behind it are stable. If your team owns the analytics layer but keeps getting stuck on launches and access, that half is worth delegating: agency Google Ads accounts and account verification take the infrastructure question off the table, while the Google Ads guide covers the structural and measurement basics.

FAQ

What is campaign data import in GA4?

A mechanism for uploading daily cost, clicks and impressions from non-Google advertising channels so GA4 can report cost per click and return on ad spend across all sources. Its previous name was cost data import.

Do I need to import Google Ads spend?

No. Google Ads data flows in automatically through the account link. The import exists for third-party channels.

Which fields are required?

utm_source, utm_medium and date, plus at least one metric — clicks, cost or impressions. If you include cost, you also need currency in ISO 4217.

How does GA4 join the data?

On three fields: utm_source, utm_medium and date. The match must be exact, including letter case.

Can I backfill historical spend?

Yes. The join happens at query time, so imported cost applies to events that were already processed.

What happens if I upload the same period twice?

Rows with the same keys overwrite each other; GA4 does not sum them. Re-uploading recent days is normal practice because ad platforms restate spend after the fact.

Why is my match rate low?

Almost always tagging mismatch: the values in your file differ from what actually arrives in the links. Remember case sensitivity — “Facebook” and “facebook” are different.

Can I build audiences from imported cost?

No. Query-time data is unavailable when creating audiences in Analytics or segments in Explorations.

What are the limits?

1 GB per import source, 1 GB total for campaign data, 120 uploads per property per day, and up to 24 hours before data appears in reports.

Which platforms have direct connectors?

Meta, Pinterest, Reddit, Snap and TikTok. They run automatically every day and pull up to 24 months of history on connection.

Why can’t I use a connector?

Direct connectors require all traffic from a platform to use one utm_source value and one utm_medium value. With multiple variants in play, use CSV, Google Sheets or BigQuery instead.

What happens if I delete the import source?

Campaign data disappears from reports, because the join is performed at query time and never written into processed data.

Similar Posts