Summary
The CONVERSION_NOT_FOUND error occurs when the Google Ads API cannot locate a conversion that matches the supplied conversion identifier (e.g., order_id). This usually means the conversion was never uploaded, was rejected as invalid/spam, or was associated with the wrong click identifier (e.g., gbraid/wbraid instead of gclid).
Key takeaways
- Verify the conversion was successfully uploaded before attempting adjustments.
- Ensure the
customer_idmatches the account that owns the conversion action. - Use the correct click‑ID (
gclid) for enhanced conversions on the web.
Root Cause
- Missing or mismatched conversion upload – the conversion record does not exist in the account at the time of the adjustment request.
- Wrong click identifier – the click was attributed with
gbraid/wbraid(app or iOS SKAdNetwork) while the API expects agclid. - Invalid or spam‑filtered conversion – the upload was rejected by Google’s validation layer (duplicate, zero value, policy violation).
- Incorrect
customer_idorconversion_action_id– the request targets a different account or conversion action than the one used during upload.
Why This Happens in Real Systems
- Asynchronous pipelines – conversion uploads and adjustment calls often run in separate jobs; race conditions leave the adjustment running before the upload finishes.
- Environment drift – dev, staging, and prod environments use different customer IDs; a hard‑coded ID can point to the wrong account.
- Dynamic click‑ID handling – code that blindly copies
gbraid/wbraidfrom a mobile redirect URI into the API payload will break enhanced‑conversion uploads. - Insufficient logging – missing logs for the initial upload make it hard to confirm whether the record ever existed.
Real-World Impact
- Revenue loss – conversions are not attributed, causing inaccurate ROI reporting.
- Budget misallocation – campaigns may be under‑ or over‑funded based on faulty conversion data.
- Compliance risk – repeated spam‑filtered uploads can trigger account throttling or suspension.
- Debug overload – support tickets pile up as marketers cannot see the cause without deep API knowledge.
Example or Code (if necessary and relevant)
# Upload a conversion
conversion_service = client.get_service("ConversionUploadService")
request = client.get_type("UploadClickConversionsRequest")
request.customer_id = "123-456-7890"
conv = request.conversions.add()
conv.conversion_action = "customers/123-456-7890/conversionActions/987654321"
conv.gclid = "CL6V5eW3..."; # Must be a gclid, not gbraid/wbraid
conv.conversion_date_time = "2024-05-30 14:23:01-07:00"
conv.currency_code = "USD"
conv.adjustments.append(
client.get_type("ClickConversionAdjustment")(
adjustment_type=client.enums.ClickConversionAdjustmentTypeEnum.INCREASE,
gclid="CL6V5eW3...",
order_id="ORDER123",
adjustment_value=10.0,
)
)
response = conversion_service.upload_click_conversions(request=request)
print(response)
How Senior Engineers Fix It
- Add idempotent check: query
GoogleAdsService.searchfor theorder_idbefore sending an adjustment. - Synchronize pipelines: use a message queue with visibility timeout to guarantee the upload job completes before the adjustment job runs.
- Validate click IDs: filter out records where
gbraidorwbraidis present; log and skip them. - Centralize config: store
customer_idandconversion_action_idin a single source of truth (e.g., a config service) and reference it everywhere. - Implement detailed logging: capture the full upload request, response status, and any validation errors; surface them in monitoring dashboards.
- Automated tests: write integration tests that simulate successful upload → adjustment flow and assert no
CONVERSION_NOT_FOUNDerrors.
Why Juniors Miss It
- Assume the upload always succeeds and skip verification of the upload response.
- Mix up click identifiers (
gbraid/wbraidvs.gclid) because they look similar in logs. - Hard‑code IDs for testing and forget to replace them for production, leading to cross‑account mismatches.
- Overlook asynchronous timing, firing adjustment requests immediately after a batch upload without waiting for completion.
- Neglect error handling: they treat non‑200 responses as “nothing to do” instead of retrying or alerting.