vendor/google-ads-click-conversions · vendor documented
Click conversion uploads need a click ID or hashed user
The REST upload wants conversionAction, a timestamp with a timezone offset, partialFailure true, and either a click ID or hashed userIdentifiers. conversionValue needs currencyCode. This is not the /pagead/conversion image and not UploadConversionAdjustments.
conversionDateTime is not ISO 8601
Google wants yyyy-mm-dd hh:mm:ss+|-hh:mm. A T separator or a Z suffix fails the format even when the instant is right.
Rule: vendor.google-ads-click-conversions.body.conversionDateTime.invalid
conversionValue needs currencyCode
Google documents the ISO 4217 code together with the conversion value. A number without a currency is incomplete.
Rule: vendor.google-ads-click-conversions.body.value_requires_currency
What this pack matches
Rules
Codes are stable. A finding in CI, MCP, or the playground lands on the same id.
| Field | Required | What it checks | Rule ids | Source |
|---|---|---|---|---|
conversions |
required | UploadClickConversions requires a `conversions` array. Fix: Send at least one ClickConversion in `conversions`. | vendor.google-ads-click-conversions.body.conversions.missing |
docs |
partialFailure |
required | Google documents `partial_failure` as required, and the upload guides say to always send true. Fix: Set `partialFailure` to `true`. | vendor.google-ads-click-conversions.body.partialFailure.missingvendor.google-ads-click-conversions.body.partialFailure.emptyvendor.google-ads-click-conversions.body.partialFailure.invalid |
docs |
conversionAction |
required | It is the conversion action resource name, and every uploaded click conversion requires it. Fix: Set `conversionAction` to `customers/{id}/conversionActions/{id}`. | vendor.google-ads-click-conversions.body.conversionAction.missingvendor.google-ads-click-conversions.body.conversionAction.empty |
docs |
conversionDateTime |
required | Google documents the conversion time with a timezone offset as `yyyy-mm-dd hh:mm:ss+|-hh:mm`. Fix: Send a timestamp such as `2026-08-21 12:00:00+00:00`. | vendor.google-ads-click-conversions.body.conversionDateTime.missingvendor.google-ads-click-conversions.body.conversionDateTime.emptyvendor.google-ads-click-conversions.body.conversionDateTime.invalid |
docs |
gclid |
optional | Google click ID. A click-ID upload needs exactly one of `gclid`, `gbraid`, or `wbraid`. | vendor.google-ads-click-conversions.body.gclid.empty |
docs |
gbraid |
optional | App-to-web click identifier from iOS. Alternative to `gclid`. | vendor.google-ads-click-conversions.body.gbraid.empty |
docs |
wbraid |
optional | Web-to-app click identifier. Alternative to `gclid`. | vendor.google-ads-click-conversions.body.wbraid.empty |
docs |
userIdentifiers |
optional | Hashed user identifiers for enhanced conversions for leads. The upload service accepts `hashedEmail` and `hashedPhoneNumber` only, at most five. | docs | |
userIdentifiers[].hashedEmail |
optional | Email must be normalized and SHA-256 hashed before it is sent. Fix: Lowercase and trim the address, hash it with SHA-256, and send the hex digest. | vendor.google-ads-click-conversions.body.userIdentifiers[].hashedEmail.emptyvendor.google-ads-click-conversions.body.userIdentifiers[].hashedEmail.invalid |
docs |
userIdentifiers[].hashedPhoneNumber |
optional | Phone must be E.164 and SHA-256 hashed before it is sent. Fix: Normalize to E.164, hash with SHA-256, and send the hex digest. | vendor.google-ads-click-conversions.body.userIdentifiers[].hashedPhoneNumber.emptyvendor.google-ads-click-conversions.body.userIdentifiers[].hashedPhoneNumber.invalid |
docs |
currencyCode |
optional | It is an ISO 4217 currency code for `conversionValue`. Google documents both together. Fix: Use the three-letter code, such as `USD`, together with `conversionValue`. | vendor.google-ads-click-conversions.body.currencyCode.emptyvendor.google-ads-click-conversions.body.currencyCode.invalid |
docs |
conversionValue |
optional | It is the conversion value for the advertiser. Google documents it together with `currencyCode`. Fix: Send a number such as `1.0`, with no currency symbol, together with `currencyCode`. | vendor.google-ads-click-conversions.body.conversionValue.emptyvendor.google-ads-click-conversions.body.conversionValue.invalid |
docs |
userIpAddress |
optional | It is the customer IP on the landing page after the click, sent unhashed. Google documents the device address, not the advertiser server. | vendor.google-ads-click-conversions.body.userIpAddress.empty |
docs |
orderId |
optional | It is the order ID for the conversion. Google documents one order id per conversion action, and recommends it for later adjustments. Fix: Send `orderId` as a string, or drop the empty pair. | vendor.google-ads-click-conversions.body.orderId.empty |
docs |
conversionEnvironment |
optional | It is where the conversion was recorded. Google documents `APP` or `WEB`. Fix: Set `conversionEnvironment` to `APP` or `WEB`. | vendor.google-ads-click-conversions.body.conversionEnvironment.emptyvendor.google-ads-click-conversions.body.conversionEnvironment.invalid |
docs |
customerType |
optional | It is whether the converting user is new or returning. Google documents `NEW` or `RETURNING`. Fix: Set `customerType` to `NEW` or `RETURNING`. | vendor.google-ads-click-conversions.body.customerType.emptyvendor.google-ads-click-conversions.body.customerType.invalid |
docs |
consent.adUserData |
optional | It is consent for ad user data on the click conversion. Google documents `GRANTED` or `DENIED`. Fix: Send `consent.adUserData` as `GRANTED` or `DENIED`. | vendor.google-ads-click-conversions.body.consent.adUserData.emptyvendor.google-ads-click-conversions.body.consent.adUserData.invalid |
docs |
cartData.merchantId |
optional | It is the Merchant Center ID where the cart items are uploaded. Fix: Send `cartData.merchantId` as a whole number. | vendor.google-ads-click-conversions.body.cartData.merchantId.emptyvendor.google-ads-click-conversions.body.cartData.merchantId.invalid |
docs |
cartData.feedCountryCode |
optional | It is the country code of the Merchant Center feed the items come from. Fix: Send `cartData.feedCountryCode`, or drop the empty pair. | vendor.google-ads-click-conversions.body.cartData.feedCountryCode.empty |
docs |
cartData.feedLanguageCode |
optional | It is the language code of the Merchant Center feed the items come from. Fix: Send `cartData.feedLanguageCode`, or drop the empty pair. | vendor.google-ads-click-conversions.body.cartData.feedLanguageCode.empty |
docs |
cartData.localTransactionCost |
optional | It is cart-level discounts such as free shipping or coupons. The currency is the same as `currencyCode`. Fix: Send `cartData.localTransactionCost` as a number, such as `2.50`, without a currency symbol. | vendor.google-ads-click-conversions.body.cartData.localTransactionCost.emptyvendor.google-ads-click-conversions.body.cartData.localTransactionCost.invalid |
docs |
cartData.items[].productId |
optional | It is the Merchant Center product identifier for a purchased item. Fix: Set `cartData.items[].productId` to the Merchant Center id, or drop the empty pair. | vendor.google-ads-click-conversions.body.cartData.items[].productId.empty |
docs |
cartData.items[].quantity |
optional | It is how many of that item were sold. Fix: Send a whole number in `cartData.items[].quantity`, such as `1`. | vendor.google-ads-click-conversions.body.cartData.items[].quantity.emptyvendor.google-ads-click-conversions.body.cartData.items[].quantity.invalid |
docs |
cartData.items[].unitPrice |
optional | It is the unit price excluding tax, shipping, and cart-level discounts. Fix: Send `cartData.items[].unitPrice` as a number, such as `19.99`, without a currency symbol. | vendor.google-ads-click-conversions.body.cartData.items[].unitPrice.emptyvendor.google-ads-click-conversions.body.cartData.items[].unitPrice.invalid |
docs |
customVariables[].conversionCustomVariable |
optional | It is the custom conversion variable resource name. Fix: Set `conversionCustomVariable` to `customers/{id}/conversionCustomVariables/{id}`. | vendor.google-ads-click-conversions.body.customVariables[].conversionCustomVariable.empty |
docs |
customVariables[].value |
optional | It is the custom variable value. Google documents that it must not carry private customer data such as email or phone. Fix: Send a non-empty custom variable value with no email or phone. | vendor.google-ads-click-conversions.body.customVariables[].value.empty |
docs |
externalAttributionData.externalAttributionCredit |
optional | It is the fraction of the conversion attributed to the Google Ads click. Fix: Send `externalAttributionCredit` as a number, such as `0.3`. | vendor.google-ads-click-conversions.body.externalAttributionData.externalAttributionCredit.emptyvendor.google-ads-click-conversions.body.externalAttributionData.externalAttributionCredit.invalid |
docs |
externalAttributionData.externalAttributionModel |
optional | It is the name of the external attribution model. Fix: Send `externalAttributionModel`, or drop the empty pair. | vendor.google-ads-click-conversions.body.externalAttributionData.externalAttributionModel.empty |
docs |
body.click_id_or_user_required |
required | The conversion has no click ID and no `userIdentifiers`. Google documents a `gclid`, `gbraid`, or `wbraid` for click-ID uploads, or hashed user identifiers for enhanced conversions for leads. Fix: Send `gclid` (or `gbraid` / `wbraid`), or send hashed `userIdentifiers`. | vendor.google-ads-click-conversions.body.click_id_or_user_required |
docs |
body.value_requires_currency |
required | The conversion sends `conversionValue` without `currencyCode`. Google documents the ISO 4217 code together with the value. Fix: Add `currencyCode`, such as `USD`. | vendor.google-ads-click-conversions.body.value_requires_currency |
docs |
body.currency_requires_value |
required | The conversion sends `currencyCode` without `conversionValue`. Google documents both together. Fix: Add `conversionValue` as a number, with no currency symbol. | vendor.google-ads-click-conversions.body.currency_requires_value |
docs |
body.unhashed_email |
required | A field carries what looks like a raw email address. Google requires email as `hashedEmail`, SHA-256 hashed after normalization. Fix: Normalize the address, hash it with SHA-256, and send `userIdentifiers[].hashedEmail`. | vendor.google-ads-click-conversions.body.unhashed_email |
docs |
body.hashed_plaintext_field |
required | `userIpAddress` looks like a SHA-256 digest, but Google documents it as the customer IP, unhashed. Fix: Send the raw IP address of the customer's device. | vendor.google-ads-click-conversions.body.hashed_plaintext_field |
docs |
Validate a payload
pixellint validate json @payload.json --rulepack vendor/google-ads-click-conversions
Try this failing payload in the playground. Click conversion upload with a hashed userIpAddress.
{"partialFailure":true,"conversions":[{"conversionAction":"customers/1/conversionActions/2","conversionDateTime":"2026-08-21 12:00:00+00:00","gclid":"TeSter-123","userIpAddress":"a85e9ca18f34935ab9b0381b25bfad2455444112b0149270fd88e3da172fe196"}]}
cargo install pixellint
·
npm install pixellint