pixellint

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

Hosts
googleads.googleapis.com
Paths
…uploadCallConversions…
Vendor docs
developers.google.com/google-ads/api/docs/conversions/upload-calls

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.missing
vendor.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.missing
vendor.google-ads-call-conversions.body.partialFailure.empty
vendor.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.missing
vendor.google-ads-call-conversions.body.conversionAction.empty
vendor.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.missing
vendor.google-ads-call-conversions.body.callerId.empty
vendor.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.missing
vendor.google-ads-call-conversions.body.callStartDateTime.empty
vendor.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.missing
vendor.google-ads-call-conversions.body.conversionDateTime.empty
vendor.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.empty
vendor.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.empty
vendor.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.empty
vendor.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.missing
vendor.google-ads-call-conversions.body.conversionCustomVariable.empty
vendor.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.missing
vendor.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.missing
vendor.google-ads-call-conversions.http.method.empty
vendor.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.missing
vendor.google-ads-call-conversions.http.content_type.empty
vendor.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.missing
vendor.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.missing
vendor.google-ads-call-conversions.http.path.empty
vendor.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.missing
vendor.google-ads-call-conversions.http.headers.authorization.empty
vendor.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.missing
vendor.google-ads-call-conversions.http.headers.developer-token.empty
vendor.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.empty
vendor.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.empty
vendor.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