Upload offline conversions from Google Sheets or CSV

Google SheetsCSVAds Warmup
Live feed by webhook

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.

Setup in 5 minutes
No credit card
One lead from a Meta ad
From form fill to won deal in HighLevel
With DataCops
Form fillSent to Meta
Booked callSent to Meta
Showed upSent to Meta
Deal wonSent with its value
Matched to the original ad click by email

Trusted by agencies and brands running paid media

AffilinoBigfishClever DigitalKeetraxLegendListingLogicNumeroStormZealdBurst Digital
Definition

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

Past customers, one CSV
What your ads see today Sheet Ads Warmup CSV Ad platforms
With DataCops Sheet Ads Warmup CSV Ad platforms
New sales, every day
What your ads see today New row Webhook Ad platforms
With DataCops New row Webhook Ad platforms

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.

  1. email: the customer's email address, no spaces.
  2. phone: with the country code, for example +14155550137. Format the column as text, or the plus sign and leading zeros disappear.
  3. event: the stage, such as lead, booked, showed, won or paid.
  4. date and time: when the event happened, in one consistent format.
  5. value: the amount as a plain number, no currency symbol or thousands separator.
  6. currency: a three-letter code such as USD, GBP or EUR.
  7. order_id: your own ID for the sale. The same order ID sent twice counts once, so this is what protects you from doubles.
  8. 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.

  1. Every row has an email or a phone number, ideally both. A row with neither cannot be matched to anyone.
  2. Phone numbers carry the country code and click ID columns are set to text, so nothing was reformatted on the way in.
  3. Duplicates are gone. Give every sale an order ID, and remove rows for the same sale that appear twice.
  4. 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.

Real people only

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 bots
Meta, delivery
Real people only
Bots and datacenter traffic never reach Meta. VPNs and proxies too, if you choose.
Send everything
Meta gets every visitor, bots included.
Lead from a bot Skipped

Set up a sheet or CSV feed

About 5 minutes for the site, then upload once or connect the sheet.

  1. Step 1
    code

    Add the DataCops script
    One script and one DNS record keep every ad click on your own domain.

  2. Step 2
    upload_file

    Upload past customers
    Send the CSV through Ads Warmup, up to 20,000 rows on a paid plan.

  3. Step 3
    hub

    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.

Stop losing rows to a monthly upload

Start free, then send new sales the day they close.

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