Skip to content

Conversions and customer lists ​

This page is for the marketer. It covers two things that you do with your own records, such as a CRM export or a sales sheet:

  • Sending conversions: telling a platform which leads and clicks became customers, so it can count them for the ads that brought them.
  • Uploading a customer list: giving a platform a list of people to use as an audience, to keep ads away from existing customers or to reach them.

Each exists on Meta, Google Ads and LinkedIn, which makes six uploads.

These are people's contact details

Both send people's details to an advertising platform. Send only a list that you are allowed to use this way. The server hashes what the platform accepts as a hash before it sends, and stores nothing of a row. See What is hashed.

What has to be on first ​

All six are off on a new installation. An administrator opens each one separately:

UploadPageSwitch
Conversions to MetaMeta app, under Meta AdsAllow sending conversions to a pixel
Customer list on MetaMeta app, under Meta AdsAllow customer lists as audiences
Conversions to GoogleSafety limits, under Google Ads limitsAllow uploading offline conversions to Google
Customer list on GoogleSafety limits, under Google Ads limitsAllow Customer Match lists on Google
Conversions to LinkedInLinkedIn app, under LinkedIn AdsConversions: ask for rw_conversions
Customer list on LinkedInLinkedIn app, under LinkedIn AdsMatched audiences: ask for rw_dmp_segments

You also need:

  • Write access for your user.
  • The permission on your own connection, for Google and LinkedIn. Each of those four switches adds a permission to the sign-in. If you connected before the switch was opened, reconnect on Google connection or LinkedIn connection. The two Meta switches ask for no new permission.

When something is missing, the answer says what, and where it is changed. For the administrator's side, see Contact data.

Three ways to hand over the rows ​

  1. A file in a data folder. Your AI client names the path of a CSV file that lies in a folder on the server which the administrator opened for this. The rows never pass through the conversation. This is the best way, and the only way for more than 2,000 rows.
  2. Values that are already hashed. You hash the emails, phone numbers and names yourself, by the platform's own rules, and say that they are hashed. The server checks that each is a SHA-256 hash (64 hexadecimal characters) and passes it on.
  3. Rows in the conversation. Up to 2,000 rows. The server hashes them before sending, but your AI client has seen them in plain form.

For conversions there is a better way still, which needs no contact detail at all: see Send conversions.

The file ​

  • A CSV in UTF-8, with at most 500,000 rows.
  • The first row names the columns. A file with no header row is refused.
  • Commas, semicolons or tabs between values all work.
  • It must lie inside a data folder. A path outside one is refused. The file is read where it lies and is never copied.
  • A column that the upload does not take is named in the answer and ignored. It is never sent.
  • Common spellings of a column name are understood, such as mobile for phone and surname for last_name.

The columns for a person are the same in every upload that takes them:

ColumnWhat goes in it
emailAn email address.
phoneMeta and Google only. A phone number. Write it with the country code, as +966... or 00966.... For numbers written without one, tell the AI client the country's dialling code. A number that starts with a single zero and has no code cannot be used.
first_name, last_nameThe person's name.
city, state, zipMeta only (zip also for Google).
countryTwo letters, such as SA, EG or KW.

Each upload adds its own columns, below.

Send conversions ​

Send the won deals in D:\CRM-exports\won-october.csv to Meta as conversions for the Acme pixel.

Upload these closed sales to Google as offline conversions. Everyone in the file agreed to their data being used for advertising.

The preview says how many rows were read, how many would be sent, and how many were left out and why. A row is named by its number, never by what is in it. Nothing is sent until you confirm.

To Meta ​

Needs: a pixel (dataset) of the ad account.

Columns: event_name and event_time on every row, then either lead_id, or email / phone with the other person columns. Optional: value, currency, event_id, external_id, crm_name.

  • Prefer Meta's own lead id. If the lead came from a Meta lead form, its lead_id is in the export (see Leads). A row with a lead_id needs no email and no phone. Its event_name is the stage in your CRM's own words, such as "Qualified" or "Converted", and you say which system it comes from.
  • A row without a lead_id needs an email or a phone, and one of Meta's standard event names, such as Lead, Purchase or CompleteRegistration. A Purchase needs a value.
  • event_time must be within the last 7 days (62 for a sale in a physical shop). One older row refuses the whole call, naming the row.
  • The preview is the server's own check. Meta has no way to check events without taking them, so Meta has seen nothing until you confirm.
  • A test code from Meta's Events Manager is a real send, not a preview, and Meta counts those events too.

To Google Ads ​

Needs: a conversion action in the account whose type takes uploads. One can be made from here when the administrator allows changes to conversion actions: see Google Ads.

Columns: conversion_time on every row, then a click id (gclid, or gbraid / wbraid for a click from iOS; one of the three), or email / phone. Optional: first_name, last_name, country, zip, value, currency, order_id.

  • Prefer the click id. A row with a click id needs no contact detail. A Google lead's click id is in the export as click_id.
  • conversion_time must carry its time zone offset, as 2026-10-01T09:30:00+03:00. One without is refused.
  • Rows with an email or a phone work only when the Google Ads account has accepted Google's customer data terms and has enhanced conversions for leads switched on. The server reads both, and the refusal says where they are switched on.
  • A name is used only when the last name, the country and the postal code are all there.
  • You state consent: see Consent and terms.
  • The preview is checked by Google. The same request is sent in a mode where Google checks every row and records nothing.

To LinkedIn ​

Needs: a conversion in the ad account whose method is the Conversions API. See LinkedIn Ads.

Columns: happened_at on every row, and email, or both first_name and last_name. Optional: value, currency, event_id, company, title, country.

  • happened_at must be within the last 90 days. One older row refuses the whole call, naming the row.
  • The email and the names are hashed. A company, a job title and a country are sent as they are, because LinkedIn takes no hash of them, and only beside both names. Leave those columns out to send hashes alone.
  • The preview is the server's own check. LinkedIn has no way to check events without taking them.

Upload a customer list ​

Create a customer list called "Customers 2026" on Meta, and fill it from D:\CRM-exports\customers.csv.

Add these people to our Customer Match list on Google. They all agreed to personalised advertising, and I accept Google's Customer Match terms.

A list is made empty first and filled afterwards. Making one spends nothing. A list is an audience: to use it, add it to a campaign's targeting or exclusions.

On Meta ​

Columns: email or phone (a row needs one of them), and optionally first_name, last_name, city, state, zip, country. All are hashed.

  • You accept Meta's Custom Audience terms yourself, for the ad account, at Meta. The server never accepts them for you. If you have not, the refusal carries Meta's link.
  • When you make the list, Meta is told where its data came from. The default says that you collected it directly from your own customers. If that is not so, say so.
  • Meta says nothing back about who it matched, and shows ads to a list only once it has matched 100 people.
  • The preview is the server's own check.

On Google Ads ​

Columns: email or phone (a row needs one of them), and optionally first_name, last_name, country, zip. A name is used only when the last name, the country and the postal code are all there.

  • You state consent and accept Google's Customer Match terms: see Consent and terms.
  • A person stays in the list for up to 540 days after their last upload.
  • Google serves a list once it has matched 100 active people. A young or small account may only observe or exclude with it. Google decides this.
  • The preview is checked by Google.

On LinkedIn ​

A LinkedIn list is either a list of contacts or a list of companies. You choose when you make it, and the list's own kind then says what a row is.

Columns for contacts: email, or both first_name and last_name. Optional: title, company, country.

Columns for companies: one of company, domain, email_domain or page_url, and optionally country.

  • The email is hashed. A name, a job title and a company are sent as plain text, because LinkedIn takes them no other way. Leave them out to send hashed emails alone.
  • A company row is business data and goes as it is.
  • LinkedIn takes up to 48 hours to match a new list, and serves it only once it has 300 members.
  • The preview is the server's own check.

Some statements are yours alone. The server has no default for them, and your AI client is told to ask you and to pass on exactly what you say.

StatementWhere it is askedWhat it means
Consent to data useGoogle: conversions, and adding to or replacing a listWhether these people agreed to their data being sent to Google for advertising. Granted or denied, as you state it.
Consent to personalisationThe sameWhether they agreed to personalised advertising.
Google's Customer Match termsGoogle: adding to or replacing a listThat you accept Google's Customer Match terms. It is sent to Google as your acceptance. Without it the upload is refused.
Meta's Custom Audience termsMeta: customer listsYou accept them at Meta, for the ad account. The server only reads whether you have.
Where the data came fromMeta: making a listYour own customers, a partner, or both.

Removing people from a Google list needs none of these: Google does not ask for them there.

Whether you may lawfully use a list this way is yours to confirm. See the terms.

Sending twice ​

UploadWhat a second send doesWhat the server does about it
Conversions to MetaMay count them twice. Meta does not remove a repeat that is sent this way.A file that was already sent to that pixel is refused unless you ask to send it again.
Conversions to GoogleGoogle can recognise a repeat by its id.The same guard. A row with no order_id gets an id worked out from the row, the same on every send.
Conversions to LinkedInMay count them twice.The same guard. Give each row its own event_id where your records have one.
Any customer listNothing. A person who is already in a list stays in it once.No guard is needed.

The guard recognises a file. Rows that were given in the conversation cannot be recognised again, because nothing of them is kept. Do not send those a second time unless you mean to.

When only part goes through ​

Large uploads go in batches. If a platform refuses one batch for what is in it, the others still go, and the answer says that the upload was partly applied and which rows did not go. Fix those rows and send only them. Nothing is retried by itself.

For conversions to Meta and for both Google uploads, one bad row refuses its whole batch. LinkedIn answers a list upload row by row, so there only the refused rows are left out.

Conversions to LinkedIn are the exception: a refused batch stops the upload. The answer says how many events had already gone. Do not send the whole file again, because LinkedIn may count those twice: fix the rows and send only what did not go.

Removing and replacing ​

Taking people out of a list can change who sees your running ads, so it asks for a second, explicit confirmation. The preview is free, and on Meta it names the ad sets that use the list.

  • Remove takes the people in your rows out of the list. On LinkedIn a row is removed only when it matches what was added, so send the same columns.
  • Replace (Meta and Google) puts your rows in and takes out everyone else. If a replace stops partway, the answer says so: run it again whole. On Google the list then still holds the old people as well as the new. LinkedIn has no replace.
  • Deleting a whole list (Meta and LinkedIn) is a separate request and also asks twice. A list is not deleted while a running ad set or campaign uses it.

See How it keeps you safe.

What is hashed and what is stored ​

Before it sends, the server tidies each value by the rules of the platform it is going to and hashes it with SHA-256, wherever that platform takes a hash. A few things go as they are, because the platform takes them no other way:

  • to Google: the country and the postal code;
  • to LinkedIn: the country, and with conversions a company and a job title; in a contact list also the name;
  • ids that are not a person's details: Meta's lead id, Google's click id, your own order id.

Nothing of a row is stored on the server. The activity log keeps how many rows went in, how many were sent or left out and why, and a file's fingerprint and size. It never keeps a name, an email, a phone number or a hash.

Contact data has the full table.