Connect a CSV import¶
If your traffic data lives somewhere Squoosh doesn't have a direct connector for, you can hand it a CSV instead. Squoosh reads the file once, builds a calibration snapshot from it, and uses that snapshot the same way it uses a live Google Analytics or Shopify Analytics connection — to shape the synthetic shopper pool to match your real visitors. This page covers the file format and how to build one from a few common tools.
What the connection does¶
CSV import is a calibration source, exactly like Google Analytics or Shopify Analytics. Once you upload a file, Squoosh reads the device, geography, channel, and (optionally) conversion counts in it and builds synthetic shoppers whose mix matches what you reported.
Unlike the live connectors, a CSV import doesn't refresh itself — it's a snapshot of whatever numbers were in the file the moment you uploaded it. Uploading a new file replaces the old one; Squoosh never blends an old file with a new one or keeps history beyond the most recent upload.
The connection is not required to run a test — Squoosh can build a pool from a general e-commerce mix without it. For how the calibrated pool behaves and how the match is measured, see Synthetic shoppers.
The file format¶
The file needs an exact header row, then one data row per bucket:
dimension,bucket,sessions
device,mobile,600
device,desktop,350
device,tablet,50
geo,US,700
geo,DE,200
geo,other,100
channel,Direct,400
channel,Organic Search,400
channel,Email,200
conversion,total,30
| Column | Meaning |
|---|---|
dimension |
One of device, geo, channel, or conversion. |
bucket |
The label for that row — see the rules per dimension below. |
sessions |
A non-negative number of sessions (or, for the conversion row, conversions) in that bucket. |
Rules:
- Header must match exactly —
dimension,bucket,sessions, nothing added or reordered. devicebuckets must bemobile,desktop, ortablet. At least 80% of your total device sessions need to land in one of these three labels, or Squoosh rejects the whole file — a device breakdown that's mostly unrecognized labels usually means a template mismatch worth fixing before it's trusted.geobuckets are ISO-3166 two-letter country codes (US,DE,GB, …) or the literalotherfor everything you're not breaking out individually.channelbuckets must be exactly one of:Direct,Organic Search,Paid Search,Social,Email,Referral. Anything else —Display,Affiliates, a raw UTM value — is rejected; roll it into the closest of the six or add it to whichever bucket best represents it before uploading.conversion,total,<count>is optional. When present, Squoosh reports a conversion rate using it as the numerator. The denominator is your device rows' total sessions, or your geo rows' total if you didn't include device rows, or your channel rows' total if you included neither.- One row per bucket — don't repeat a
dimension/bucketpair. Squoosh rejects the whole file if you do, naming the duplicate rows, rather than guessing which count is right. - The file needs at least one data row — a header with nothing under it is rejected the same way.
- File limits: 1 MB and 10,000 rows.
You don't need all three dimensions. A file with just device rows still calibrates the device mix; Squoosh only fills in what you gave it and leaves the rest as a general default.
Note
Small numbers aren't fabricated into a distribution. If a dimension's total sessions come in under about 30, Squoosh leaves that dimension out of calibration rather than treating a handful of sessions as a real pattern. It'll still use whatever other dimensions clear that bar.
If a file fails to parse, Squoosh tells you which row and field caused it — fix those rows and re-upload. It never echoes the bad value back (in case it's something you didn't mean to paste in), just the row number and what's wrong with it.
Building the file from another tool¶
The template only needs sessions broken down by device, by country, and by channel, plus (optionally) a conversion count — most analytics tools can produce all three, even without a native "export for Squoosh" button.
Google Analytics 4 (Explore export). Build a Free form exploration with Sessions as the metric, and run it three times with a different breakdown dimension each time: Device category, Country, and Session default channel group (all three are standard GA4 dimensions). Export each table, then combine the rows into the template — GA4's channel groups already match five of the six canonical labels (Direct, Organic Search, Paid Search, Social, Referral); fold Email in from whatever channel GA4 assigns your email campaigns to if it isn't broken out on its own.
Heap. Heap doesn't have a single built-in device/geo/channel report the way GA4 does. Build three separate breakdowns instead — sessions or users by device type, by country, and by referrer or UTM source/medium — export each as CSV, and map the labels into the template's buckets (device type → mobile/desktop/tablet; UTM medium → the closest of the six channel labels).
Hotjar. Hotjar is built for heatmaps and session recordings, not traffic-breakdown reporting, so it's usually not where your device/geo/channel counts live even if it's your primary tool for behavior. Pull those counts from whatever does have them — your e-commerce platform's own analytics (e.g. Shopify Analytics), your CDN or hosting provider's traffic logs, or a lightweight web analytics tool running alongside Hotjar — and use those totals to fill in the template.
Anything else. If a tool can show you sessions broken down by device type, by country, and by traffic source over the same date range, it can feed this template. Export or read off each breakdown, map device labels to mobile/desktop/tablet, map countries to ISO-3166 codes (roll anything you don't break out into other), map channels to the six canonical labels, and total the counts into the three-column format above.
Change or remove the connection¶
Uploading a new file replaces the previous one entirely — there's no need to remove the old file first. Disconnecting removes the calibration source; you can upload a new file at any time to reconnect.
Note
A property uses one calibration source at a time. Connecting a CSV import clears any other analytics source as the active one, and switching to another source clears the CSV import. Switch deliberately — you can have one active, not several at once.
Troubleshooting¶
| Problem | What to do |
|---|---|
| "Header must be exactly ..." | The first line has to be dimension,bucket,sessions verbatim — check for extra spaces, reordered columns, or a stray column. |
A channel row is rejected |
Its bucket isn't one of the six canonical labels. Rename it to the closest match — Direct, Organic Search, Paid Search, Social, Email, or Referral. |
The whole file is rejected over device rows |
Fewer than 80% of your device sessions mapped to mobile, desktop, or tablet. Check for typos or a fourth device category (e.g. "Smart TV") that needs folding into one of the three. |
| "File exceeds the ... byte limit" or the row limit | Trim the file to just the breakdowns in the template — it doesn't need raw session-level data, only the aggregated bucket totals. |
| No conversion rate shows up | The conversion,total,<count> row is optional — add it if you want a conversion signal reported alongside the traffic mix. |
Related¶
- Synthetic shoppers — how the calibrated pool behaves and how the match is read.
- Connect Google Analytics and Connect Shopify — live calibration sources, if you have access to one instead.
- Keep synthetic traffic out of your analytics — synthetic shoppers stay out of your own traffic counts, so re-exporting after connecting Squoosh won't include them.