Google Ads call conversions check consent and identifiers.
Call conversions posted to the Google Ads API UploadCallConversions method. UploadClickConversions stays vendor/google-ads-click-conversions. Conversion adjustments are vendor/google-ads-conversion-adjustments. The image pixel is a different pack.
Nondefault adPersonalization values receive service-specific checks. Proto3 default values remain valid. Currency assignment and resource spelling receive scoped advice.
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 | UploadCallConversions requires a `conversions` array. Native JSON type: array. Minimum array items: 1. Maximum array items: 2000. Fix: Send at least one CallConversion in `conversions`. | vendor.google-ads-call-conversions.body.conversions.missingvendor.google-ads-call-conversions.body.conversions.invalid |
docs |
partialFailure |
required | Google documents `partial_failure` as required, and the upload guides say to always send true. Native JSON type: boolean. Fix: Set `partialFailure` to `true`. | vendor.google-ads-call-conversions.body.partialFailure.missingvendor.google-ads-call-conversions.body.partialFailure.emptyvendor.google-ads-call-conversions.body.partialFailure.invalid |
docs |
conversions[] |
optional | The vendor documents `conversions[]` in the request contract. Native JSON type: object. | vendor.google-ads-call-conversions.body.conversions[].invalid |
docs |
validateOnly |
optional | The vendor documents `validateOnly` in the request contract. Native JSON type: boolean. | vendor.google-ads-call-conversions.body.validateOnly.invalid |
docs |
root |
optional | The vendor documents `` in the request contract. Native JSON type: object. | vendor.google-ads-call-conversions.body.root.invalid |
docs |
conversionAction |
required | It is the conversion action resource name, and every uploaded call conversion requires it. Body scope: ["conversions[]"]. Native JSON type: string. Fix: Set `conversionAction` to `customers/{id}/conversionActions/{id}`. | vendor.google-ads-call-conversions.body.conversionAction.missingvendor.google-ads-call-conversions.body.conversionAction.emptyvendor.google-ads-call-conversions.body.conversionAction.invalid |
docs |
callerId |
required | It is the caller phone number. Google documents E.164 with a leading `+`. Body scope: ["conversions[]"]. Native JSON type: string. Fix: Send E.164, such as `+16502531234`. | vendor.google-ads-call-conversions.body.callerId.missingvendor.google-ads-call-conversions.body.callerId.emptyvendor.google-ads-call-conversions.body.callerId.invalid |
docs |
callStartDateTime |
required | Google documents the call start time as `yyyy-mm-dd hh:mm:ss+|-hh:mm`. Body scope: ["conversions[]"]. Native JSON type: string. Fix: Send a timestamp such as `2026-08-21 12:00:00+00:00`. | vendor.google-ads-call-conversions.body.callStartDateTime.missingvendor.google-ads-call-conversions.body.callStartDateTime.emptyvendor.google-ads-call-conversions.body.callStartDateTime.invalid |
docs |
conversionDateTime |
required | Google documents the conversion time with a timezone offset as `yyyy-mm-dd hh:mm:ss+|-hh:mm`. It must be after the call start. Body scope: ["conversions[]"]. Native JSON type: string. Fix: Send a timestamp such as `2026-08-21 12:05:00+00:00`. | vendor.google-ads-call-conversions.body.conversionDateTime.missingvendor.google-ads-call-conversions.body.conversionDateTime.emptyvendor.google-ads-call-conversions.body.conversionDateTime.invalid |
docs |
conversionValue |
optional | It is the conversion value for the advertiser. Google documents a non-negative number together with `currencyCode`. Body scope: ["conversions[]"]. Native JSON type: number or string. Fix: Send a number such as `1.0`, with no currency symbol, together with `currencyCode`. | vendor.google-ads-call-conversions.body.conversionValue.emptyvendor.google-ads-call-conversions.body.conversionValue.invalid |
docs |
currencyCode |
optional | It is an ISO 4217 currency code for `conversionValue`. Body scope: ["conversions[]"]. Native JSON type: string. Fix: Use the three-letter code, such as `USD`. | vendor.google-ads-call-conversions.body.currencyCode.emptyvendor.google-ads-call-conversions.body.currencyCode.invalid |
docs |
consent.adUserData |
optional | Google documents `consent.ad_user_data` on the CallConversion object. Body scope: ["conversions[]"]. Native JSON type: string or integer. Fix: Send `GRANTED` or `DENIED`. | vendor.google-ads-call-conversions.body.consent.adUserData.emptyvendor.google-ads-call-conversions.body.consent.adUserData.invalid |
docs |
consent |
optional | The vendor documents `consent` in the request contract. Body scope: ["conversions[]"]. Native JSON type: object. | vendor.google-ads-call-conversions.body.consent.invalid |
docs |
customVariables |
optional | Body scope: ["conversions[]"]. Native JSON type: array. | vendor.google-ads-call-conversions.body.customVariables.invalid |
docs |
customVariables[] |
optional | Body scope: ["conversions[]"]. Native JSON type: object. | vendor.google-ads-call-conversions.body.customVariables[].invalid |
docs |
consent.adPersonalization |
optional | Google limits non-default ad personalization consent to OfflineUserDataJobService and UserDataService. This proto3 enum has implicit presence: UNSPECIFIED, numeric zero and null retain default or unset behavior. Body scope: ["conversions[]"]. Presence diagnostic severity: error. Native JSON type: string or integer. Fix: Remove non-default adPersonalization from this upload; keep supported adUserData consent according to the integration. | vendor.google-ads-call-conversions.body.consent.adPersonalization.invalid |
docs |
body.value_requires_currency |
required | The conversion sends `conversionValue` without `currencyCode`. Google documents the ISO 4217 code together with the value. Body scope: ["conversions[]"]. Fix: Add `currencyCode`, such as `USD`. | vendor.google-ads-call-conversions.body.value_requires_currency |
docs |
body.currency_requires_value |
required | The conversion sends `currencyCode` without `conversionValue`. Google documents both together. Body scope: ["conversions[]"]. Fix: Add `conversionValue` as a non-negative number. | vendor.google-ads-call-conversions.body.currency_requires_value |
docs |
body.callStartDateTime.calendar_invalid |
required | The conversion timestamp must represent a valid calendar date, time and timezone offset. Body scope: ["conversions[]"]. | vendor.google-ads-call-conversions.body.callStartDateTime.calendar_invalid |
docs |
body.conversionDateTime.calendar_invalid |
required | The conversion timestamp must represent a valid calendar date, time and timezone offset. Body scope: ["conversions[]"]. | vendor.google-ads-call-conversions.body.conversionDateTime.calendar_invalid |
docs |
body.conversion_after_call |
required | The conversion time must be after the call start time, accounting for timezone offsets. Body scope: ["conversions[]"]. | vendor.google-ads-call-conversions.body.conversion_after_call |
docs |
body.conversionAction.resource_name |
recommended | Check the canonical conversion action resource spelling: customers/{customer_id}/conversionActions/{conversion_action_id}. This advice does not check ownership, existence or equality with the upload customer; Google ignores the customer component for conversion-action lookup. Body scope: ["conversions[]"]. | vendor.google-ads-call-conversions.body.conversionAction.resource_name |
docs |
body.currencyCode.assignment |
recommended | The three-letter currency value is not assigned in the built-in current or historical ISO 4217 lists. Registry advice does not establish Google account eligibility or currency support. Body scope: ["conversions[]"]. | vendor.google-ads-call-conversions.body.currencyCode.assignment |
docs |
body.consent.adPersonalization.forbidden |
required | Non-default ad personalization consent is supported only by OfflineUserDataJobService and UserDataService. This conversion upload must leave it unspecified. Body scope: ["conversions[]"]. | vendor.google-ads-call-conversions.body.consent.adPersonalization.forbidden |
docs |
body.consent.adPersonalization.invalid |
required | Use an enum name or integer spelling. Unspecified zero is retained; non-default consent belongs to other services. Body scope: ["conversions[]"]. | vendor.google-ads-call-conversions.body.consent.adPersonalization.invalid |
docs |
root |
optional | Body scope: ["conversions[].customVariables[]","conversions[].custom_variables[]"]. Native JSON type: object. | vendor.google-ads-call-conversions.body.root.invalid |
docs |
conversionCustomVariable |
required | Body scope: ["conversions[].customVariables[]","conversions[].custom_variables[]"]. Native JSON type: string. | vendor.google-ads-call-conversions.body.conversionCustomVariable.missingvendor.google-ads-call-conversions.body.conversionCustomVariable.emptyvendor.google-ads-call-conversions.body.conversionCustomVariable.invalid |
docs |
value |
required | Body scope: ["conversions[].customVariables[]","conversions[].custom_variables[]"]. Native JSON type: string. | vendor.google-ads-call-conversions.body.value.missingvendor.google-ads-call-conversions.body.value.invalid |
docs |
method |
required | This published ingestion operation uses HTTP POST. Complete HTTP capture contract. Native JSON type: string. | vendor.google-ads-call-conversions.http.method.missingvendor.google-ads-call-conversions.http.method.emptyvendor.google-ads-call-conversions.http.method.invalid |
docs |
content_type |
recommended | Use a published request media type. Complete HTTP capture contract. Presence diagnostic severity: warning. Value diagnostic severity: warning. Native JSON type: string. | vendor.google-ads-call-conversions.http.content_type.missingvendor.google-ads-call-conversions.http.content_type.emptyvendor.google-ads-call-conversions.http.content_type.invalid |
docs |
body |
required | The request body is a JSON object. Complete HTTP capture contract. Native JSON type: object. | vendor.google-ads-call-conversions.http.body.missingvendor.google-ads-call-conversions.http.body.invalid |
docs |
path |
required | REST conversion upload requires a versioned customer RPC path. Complete HTTP capture contract. Native JSON type: string. | vendor.google-ads-call-conversions.http.path.missingvendor.google-ads-call-conversions.http.path.emptyvendor.google-ads-call-conversions.http.path.invalid |
docs |
headers.authorization |
required | Every Google Ads API request requires an OAuth Bearer token. Complete HTTP capture contract. Native JSON type: string. | vendor.google-ads-call-conversions.http.headers.authorization.missingvendor.google-ads-call-conversions.http.headers.authorization.emptyvendor.google-ads-call-conversions.http.headers.authorization.invalid |
docs |
headers.developer-token |
required | Every Google Ads API request requires a developer token. Complete HTTP capture contract. Native JSON type: string. | vendor.google-ads-call-conversions.http.headers.developer-token.missingvendor.google-ads-call-conversions.http.headers.developer-token.emptyvendor.google-ads-call-conversions.http.headers.developer-token.invalid |
docs |
headers.login-customer-id |
optional | Manager customer ID, when supplied, omits hyphens. Complete HTTP capture contract. Native JSON type: string. | vendor.google-ads-call-conversions.http.headers.login-customer-id.emptyvendor.google-ads-call-conversions.http.headers.login-customer-id.invalid |
docs |
headers.linked-customer-id |
optional | Linked account customer ID, when supplied, omits hyphens. Complete HTTP capture contract. Native JSON type: string. | vendor.google-ads-call-conversions.http.headers.linked-customer-id.emptyvendor.google-ads-call-conversions.http.headers.linked-customer-id.invalid |
docs |
Validate a payload
pixellint validate request @request.json --rulepack vendor/google-ads-call-conversions
Try this failing payload in the playground. An example with a validation finding.
{
"url": "https://googleads.googleapis.com/v25/customers/1234567890:uploadCallConversions",
"method": "POST",
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer synthetic-token",
"developer-token": "synthetic-developer"
},
"body": "{\"partialFailure\":true,\"conversions\":[{\"conversionAction\":\"customers/1234567890/conversionActions/987654321\",\"callerId\":\"+16502531234\",\"callStartDateTime\":\"2026-08-21 12:00:00+00:00\",\"conversionDateTime\":\"2026-08-21 12:05:00+00:00\",\"conversionValue\":1.0,\"currencyCode\":\"USD\",\"consent\":{\"adPersonalization\":\"GRANTED\"}}]}"
}
cargo install pixellint
·
npm install pixellint