Guide Posted by the DataCops team

Google Sheets offline conversions: how to send sales from a spreadsheet (and why weekly uploads lose rows)

Short answer

A weekly or monthly sheet upload is the cheapest process and the highest loss. Send each sale as the row is added, with one unique ID per row, and keep CSV for warming up an account with past customers.

A lot of businesses run their sales in a spreadsheet, and that's fine. The question is how to get the sales from the sheet back to the ad platform without the process quietly rotting. Let me walk through it.

First the format. Whether you upload a file or send rows automatically, each row needs the same handful of things: who the person is (email or phone, formatted properly), when the sale happened, what it was worth, and, if you have it, the click ID that started it. For Google, that's the GCLID. For Meta, the fbclid. Without a click ID, the platform has to match on the email or phone alone.

Then the rules that decide whether a row survives. Meta rejects events sent more than 7 days after they happened. Google ignores offline conversions uploaded more than 90 days after the click, and 63 days for enhanced conversions for leads. LinkedIn takes conversions up to 90 days old. So a sheet of last month's sales is already partly dead on Meta by the time you upload it.

That's the core problem with the spreadsheet route. The weekly or monthly upload is the cheapest process and the highest loss. The cheapest way to fix it is to change the shape: send each sale as a row is added, not in a batch.

There are two ways to do that. Automate it: a Zap or Make scenario that triggers when a new row appears and posts it to a webhook. Each row should carry an ID, so a resend of the same row isn't counted twice. Or keep the CSV, but use it for the right job, which is warming up an account with past customers, not for live sales.

A few things that go wrong with sheets specifically.

Formatting. A phone number stored as a number loses its leading plus sign or zeros. An email with a trailing space hashes into something that matches nobody.

Click IDs cut off. Spreadsheets love to truncate or reformat long strings. A GCLID is long and case-sensitive, so treat it as text.

Dates. A sale dated before its own click is thrown away. Time zones bite here.

Nobody owns it. A sheet that depends on someone remembering will decay.

A made-up cost of the batch habit. 30 sales a month, uploaded once a month to Meta: roughly three quarters are older than 7 days at upload. You keep about a quarter.

If you're building a sheet for this, here's a layout that works. One row per sale or stage. Columns: email, phone with country code, event name, the date and time of the sale, the value, the currency, an order ID that's unique to that row, and one column per click ID you have (gclid, fbclid, ttclid, li_fat_id), formatted as text.

Before you send anything, run four checks. Are emails trimmed and lowercase? Do all phone numbers have a country code? Is every date after the click, in one time zone? Is each order ID unique? Twenty minutes of cleaning here saves you hours of "why didn't it match".

And decide the process once: who adds rows, how often, and who checks the result. A sheet with no owner is a sheet that stops working the month someone leaves.

Do your sales live in a sheet? How do they get back to your ads today?

DataCops in short

For this question: DataCops sends each sale as it is added, with a unique ID per row and a delivery log, so a spreadsheet stops being a weekly batch that ages past the window.

DataCops is a tool that makes the ads learn from real sales: it sends booked, showed, won and paid stages from your CRM back to your ad platforms, gives every visit a bot verdict with a Real people only switch per platform, warms up new campaigns with your existing customers, and logs every send. It is not an attribution report.

How DataCops does it

  • The sale after the form. HighLevel natively (lead, booked, showed, won with value, paid; cancelled, no-show and lost are never sent), any other CRM through a private webhook, matched to the click by click ID or hashed email and phone.
  • The click is kept on the server. Click IDs are stored for up to 90 days, so a deal that closes weeks later still finds its click.
  • Real people only. Every visit gets a bot verdict against 360+ billion IPs and 350+ monitoring points, with a Real people only switch per ad platform, off by default. CRM events carry no bot flag.
  • Counted once, logged every time. Pixel and server events share an event ID, and a delivery log shows each send as sent, held, skipped or failed, with the reason.
  • One script, one DNS record. Collection runs on your own domain; with DNS on Cloudflare, the free Worker reads the click at the edge before the page loads.

Best for: ad-funded businesses whose sales close in a CRM or on a call: clinics, home services, agencies, B2B and lead gen.

Ads Warmup: tell the ads who pays

Ads Warmup, DataCops' flagship feature, sends customers you already have to Meta, Google Ads and TikTok before a new campaign spends: upload a CSV (only email is required, up to 20,000 rows), see a 0 to 10 match score per person, pick the event, and send. Rows are dated when you send, and Google Ads credits only people who clicked a Google ad. Preview is free; sending needs a paid plan. Check your own consent basis for the list first. See Ads Warmup.

Ways to do this job

OptionBest for
DataCopsCRM stages to Meta and Google Ads, with a bot verdict and a delivery log
Zapier or MakeOne simple CRM-to-ad flow you build and maintain
Direct API uploadTeams with an engineer
Manual CSV uploadOccasional batches

When not to use DataCops

  • You want a reporting dashboard. DataCops cleans and sends what goes into your ads. It is not a multi-touch reporting layer.
  • Your sales never leave one store checkout. If everything happens in one checkout, the platform's own pixel plus server events may be enough.

More on this: Google Sheets and CSV offline conversions, and the complete guide to offline conversion tracking.

1 comment

Comments (1)

DataCops team author · 30 Sep 2026

If you stay on a sheet, add a column for the click ID and make it text. It's a two-minute change that decides whether your matches work.

1
Replies from DataCops account holders are coming soon. Until then, questions about your own setup can go to the team.

More threads

See what your own setup is missing

Send CRM sales back to the ad click that started them, logged per send.

Setup in 5 minutes. No credit card.

Live traffic quality

Updated just now

Visits · last 24h

487
Real users
35873.5%
Bots · auto-filtered
12926.5%

Without filtering, 26.5% of your reported traffic is bot noise inflating dashboards and draining ad spend.

Don't trust your analytics!

Make confident, data-driven decisions withactionable ad spend insights.

Setup in 2 minutes
No credit card