Upload offline conversions from Google Sheets or CSV
A spreadsheet is a fine place to start with offline conversions, as long as you set it up right. This is the column layout, four checks to run before you upload, when to use a CSV and when to feed sales live, and why a monthly upload quietly loses rows.

Trusted by agencies and brands running paid media










What are offline conversions from a spreadsheet?
Many teams keep their real sales in a sheet: a list of who bought, when and for how much. Uploading that list tells the ad platforms which people became customers, so they can find more like them. It only works if each row can be matched to a person and is sent while the platform still accepts it.
DataCops handles this two ways. For past customers, Ads Warmup takes a CSV. For sales you add from now on, a Google Sheets automation, or Zapier, Make or n8n, posts each new row to your private sales webhook, and DataCops sends it as the sale happens.
DataCops takes a CSV of past customers through Ads Warmup and a live feed of new sales through a webhook, and sends both to Google Ads, Meta, TikTok and LinkedIn.
What your ads learn from
The sheet layout that works
One row is one sale or one step in a sale. Keep the header row exactly as below, in plain lowercase, and format every column as plain text before you paste anything in. That single habit prevents most upload problems.
- email: the customer's email address, no spaces.
- phone: with the country code, for example +14155550137. Format the column as text, or the plus sign and leading zeros disappear.
- event: the stage, such as lead, booked, showed, won or paid.
- date and time: when the event happened, in one consistent format.
- value: the amount as a plain number, no currency symbol or thousands separator.
- currency: a three-letter code such as USD, GBP or EUR.
- order_id: your own ID for the sale. The same order ID sent twice counts once, so this is what protects you from doubles.
- click ID columns: gclid, wbraid or gbraid for Google, fbclid, fbc or fbp for Meta, ttclid for TikTok, li_fat_id for LinkedIn. Format as text. A click ID that a spreadsheet turns into a number or scientific notation cannot be matched.
Four checks before you upload
Spend two minutes on these and you avoid most rejected rows.
- Every row has an email or a phone number, ideally both. A row with neither cannot be matched to anyone.
- Phone numbers carry the country code and click ID columns are set to text, so nothing was reformatted on the way in.
- Duplicates are gone. Give every sale an order ID, and remove rows for the same sale that appear twice.
- Dates are honest. The event dates are real and consistent, and you know which platform limits they fall inside: 7 days for Meta, 90 days after the click for Google Ads, up to 90 days old for LinkedIn.
Past customers or new sales: which route?
This is the decision that matters most, so make it deliberately.
Use the Ads Warmup CSV for past customers. It takes up to 20,000 rows on a paid plan and is dated when it is sent, not when the sale happened. That makes it right for a customer list you want the ad platforms to learn from now, and wrong for pretending old sales happened this week.
Use a live feed for new sales. Add each new row to the sheet, and let Google Sheets, Zapier, Make or n8n post it to your private sales webhook. DataCops sends it the same day, matched to the ad click it kept on your own domain. The sale arrives well inside every platform's window, and nobody has to remember to upload.
The platform time limits
Meta rejects events sent more than 7 days after they happened. Google Ads ignores uploads more than 90 days after the click, and enhanced conversions for leads use hashed email or phone with a 63-day window. LinkedIn accepts conversions up to 90 days old and matches on hashed email, li_fat_id, or name plus company or job title, but not on phone.
These limits are why the date column matters and why a sheet full of last year's sales does not behave like fresh conversions.
Why a monthly upload loses rows
This is a made-up example to show the arithmetic, not a customer result. A shop closes 40 sales in June. It uploads one CSV on 30 June.
The 8 sales from the last week of June are inside Meta's 7-day limit and are accepted. The 32 earlier ones, closed between 1 and 22 June, are more than 7 days old, so Meta rejects them. Google Ads is kinder: all 40 are inside 90 days of the click, provided the click ID survived. If half the sales came from Safari browsers that lost the click ID, those rows have nothing to match on.
So one upload gives Meta 8 of 40 sales, or 20 percent, and Google fewer than it should. Sending each sale on the day it closes gives every platform all 40. The fix is not a better spreadsheet. It is a shorter gap between the sale and the send.
What DataCops does and does not do
DataCops matches each row to the ad click it kept on your own domain, or by hashed email and phone, and sends it to the platforms you connected. Each row is logged as sent, held, skipped or failed, with the reason.
It does not read your Google Sheet by itself, so you either export a CSV or connect an automation that posts new rows. It does not reverse refunds on Meta or TikTok, it does not read back per-row Google Ads rejections yet, and Microsoft Ads is not supported.
Filter fake leads before you send
A bot that fills in your form becomes a lead your ads try to find more of. DataCops checks every visit for bots and datacenter traffic, and for VPNs and proxies if you choose. Switch on Real people only for a platform and flagged visits never reach it.
Sales that come from your CRM are sent as your CRM reports them, with no bot check, so qualify them there before you send.
How DataCops spots botsSet up a sheet or CSV feed
About 5 minutes for the site, then upload once or connect the sheet.
- Step 1code
Add the DataCops script
One script and one DNS record keep every ad click on your own domain. - Step 2upload_file
Upload past customers
Send the CSV through Ads Warmup, up to 20,000 rows on a paid plan. - Step 3hub
Feed new sales live
Post each new sheet row to your private sales webhook so it goes out the same day.
FAQ
Yes. Export the sheet as a CSV for past customers through Ads Warmup, or have Google Sheets, Zapier, Make or n8n post each new row to your private sales webhook so it goes out as it happens.
Works with the rest of DataCops
Conversion API
Server-side conversions to Meta, Google Ads and TikTok, no code.
See Conversion APIAds Warmup
Feed your customer list to the ad platforms before you spend.
See Ads WarmupLeadCops
Verified leads, and conversions only once a lead qualifies.
See LeadCopsOffline Conversions
CRM, store and CSV sales matched back to the ad click.
See Offline ConversionsStop losing rows to a monthly upload
Start free, then send new sales the day they close.
Setup in 5 minutes. No credit card.