Google Ads: offline conversions and Customer Match
Sending offline conversions and customer lists to Google. Each is behind an administrator's switch. 3 tools. This page is generated from the server's own tool list, version 0.1.0, and is not edited by hand. The descriptions are the ones your AI client reads, so they are written for it. All tools lists every page.
gads_upload_offline_conversions
Kind: write. It only previews the change unless dry_run is false. Not offered while the server is in read-only mode.
Tell Google which clicks and leads became customers: upload conversions from the advertiser's own records (a CRM, a sales sheet) to an UPLOAD_CLICKS conversion action, so Google can count them for the ads that brought them and bid for more like them.
hashed=true keeps plain contact details out of this conversation altogether: give email, phone and names already SHA-256 hashed by Google's rules and they are checked to be hashes and passed on. Better still, give the click id (gclid) the website or the lead form recorded and no contact detail at all. Otherwise the details are normalised and hashed on this server before they are sent. Either way nothing of a row is stored: the activity log keeps how many rows went in, how many were sent or left out and why, and a file's hash and size. These are people's contact details: send them only when the user asked for this file or list to be sent, and never repeat them elsewhere.
The two consent arguments have no default and are never yours to fill in: ask the user whether the people in the list consented to their data being sent to Google for advertising (ad_user_data) and to personalised advertising (ad_personalization), and pass exactly what they say.
A row needs a click id (gclid, or gbraid / wbraid for an iOS click; one of the three) or an email or a phone. Rows with an email or a phone work only when the account has accepted Google's customer data terms and switched on enhanced conversions for leads; the tool reads both and says where they are switched on.
The dry run is validated by Google: the same request is sent with validateOnly, so Google checks every row and records nothing. One row Google finds invalid refuses its whole batch of 2,000, and the refusal names the rows. If the answer is partly_applied, some batches went and some did not: say which rows, and send only those again. A file already sent to this conversion action from here is refused unless resend=true. Works only where an administrator has allowed uploading conversions, for a person with write access whose Google connection was granted the Data Manager permission.
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
customer_id | text | yes | 10-digit Google Ads account id that owns the conversion action. | |
conversion_action_id | text | yes | An UPLOAD_CLICKS action, from gads_list_conversion_actions. | |
ad_user_data_consent | one of GRANTED, DENIED | yes | GRANTED or DENIED, as the user states it. | |
ad_personalization_consent | one of GRANTED, DENIED | yes | GRANTED or DENIED, as the user states it. | |
conversions | list of object | no | none | Up to 2,000 rows in the call, each {"conversion_time", "gclid"? | "gbraid"? | "wbraid"?, "email"?, "phone"?, "first_name"?, "last_name"?, "country"?, "zip"?, "value"?, "currency"?, "order_id"?}. conversion_time is ISO 8601 WITH its offset (2026-10-01T09:30:00+03:00); one without is refused. value is in currency, else the account's currency. A name is used only with last name, two-letter country and postal code all present. order_id is the advertiser's own id for the sale, which lets Google recognise it again. |
path | text | no | none | Instead of conversions: a UTF-8 CSV with those columns in its first row, inside one of the server's data folders (server_status lists them). |
hashed | true or false | no | false | The email, phone and names are SHA-256 hashes already (hex). |
calling_code | text | no | none | The country's dialling code (966, 20) for phone numbers written without one. A number with + or 00 in front is taken as it is. |
event_source | one of WEB, APP, IN_STORE, PHONE, MESSAGE, OTHER | no | "WEB" | Where the conversions happened: WEB (default), APP, IN_STORE, PHONE, MESSAGE or OTHER. |
resend | true or false | no | false | Send a file again that was already sent to this action from here. |
dry_run | true or false | no | true | true = Google validates only (default). false = send, after the user confirms. |
gads_create_customer_match_list
Kind: write. It only previews the change unless dry_run is false. Not offered while the server is in read-only mode.
Create an empty Google Ads Customer Match list: an audience of people the advertiser names from its own records, to keep ads away from existing customers or to reach them. It spends nothing; fill it with gads_upload_customer_match, then put it on a campaign with gads_add_campaign_audience.
The people put in it must be the advertiser's own customers, who gave it their details and may lawfully be advertised to: that is the user's to confirm. A list serves once Google has matched 100 active people, and a young or small account may only observe or exclude with it. The dry run is validated by Google. Works only where an administrator has allowed Customer Match, for a person with write access.
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
customer_id | text | yes | 10-digit Google Ads account id. | |
name | text | yes | The list's name (unique in the account). Name it for what it is to the business ("Customers 2026"), not for what it says about the people. | |
description | text | no | none | Optional note about the list. |
membership_days | whole number | no | 540 | How long a person stays after their last upload, 1 to 540 (default). |
dry_run | true or false | no | true | true = validate only (default). false = apply, only after the user confirms. |
gads_upload_customer_match
Kind: write. It only previews the change unless dry_run is false. Removing needs confirm_remove to be true as well. Not offered while the server is in read-only mode.
Add people to a Google Ads Customer Match list from the advertiser's own records, take them out, or replace everyone in it.
hashed=true keeps plain contact details out of this conversation altogether: give email, phone and names already SHA-256 hashed by Google's rules and they are checked to be hashes and passed on. Better still, give path: a CSV in one of the server's data folders, which this conversation never sees. Otherwise the details are normalised and hashed on this server before they are sent. Either way nothing of a row is stored: the activity log keeps how many rows went in, how many were sent or left out and why, and a file's hash and size. These are people's contact details: send them only when the user asked for this file or list to be sent, and never repeat them elsewhere.
Three arguments have no usable default and are never yours to fill in when adding or replacing. Ask the user whether the people in the list consented to their data being sent to Google for advertising (ad_user_data_consent) and to personalised advertising (ad_personalization_consent), and pass exactly what they say. And ask whether they accept Google's Customer Match terms of service: accept_customer_match_terms=true is the user's acceptance, sent to Google as theirs. mode=remove needs none of the three.
mode: add (default); remove takes the people in the rows out; replace adds the rows and then takes out everyone who was in the list before. remove and replace need confirm_remove=true as well as dry_run=false, and only after the user asked for exactly that: ads may be aimed at the list, or kept away from it, right now.
The dry run is validated by Google: the same request is sent with validateOnly, so Google checks every row and changes nothing. One row Google finds invalid refuses its whole batch of 10,000, and the refusal names the rows. If the answer is partly_applied, some batches went and some did not: say which rows. Adding a person twice changes nothing, so a list may be sent again. Works only where an administrator has allowed Customer Match, for a person with write access whose Google connection was granted the Data Manager permission.
| Argument | Type | Required | Default | Description |
|---|---|---|---|---|
customer_id | text | yes | 10-digit Google Ads account id that owns the list. | |
user_list_id | text | yes | A Customer Match list, from gads_list_audiences (takes_rows) or gads_create_customer_match_list. | |
rows | list of object | no | none | Up to 2,000 rows in the call, each {"email"?, "phone"?, "first_name"?, "last_name"?, "country"?, "zip"?}. A row needs an email or a phone. A name is used only with last name, two-letter country and postal code all present. |
path | text | no | none | Instead of rows: a UTF-8 CSV with those columns in its first row, inside one of the server's data folders (server_status lists them). |
hashed | true or false | no | false | The email, phone and names are SHA-256 hashes already (hex). |
calling_code | text | no | none | The country's dialling code (966, 20) for phone numbers written without one. A number with + or 00 in front is taken as it is. |
mode | one of add, remove, replace | no | "add" | add, remove or replace. |
ad_user_data_consent | one of GRANTED, DENIED | no | none | GRANTED or DENIED, as the user states it (add, replace). |
ad_personalization_consent | one of GRANTED, DENIED | no | none | GRANTED or DENIED, as the user states it (add, replace). |
accept_customer_match_terms | true or false | no | none | true once the user accepts Google's Customer Match terms (add, replace). Never assume it. |
confirm_remove | true or false | no | false | Must be true, with dry_run=false, for remove and replace. |
dry_run | true or false | no | true | true = Google validates only (default). false = send, after the user confirms. |