Fixing CONVERSION_NOT_FOUND Errors in Google Ads API

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_id matches 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 a gclid.
  • Invalid or spam‑filtered conversion – the upload was rejected by Google’s validation layer (duplicate, zero value, policy violation).
  • Incorrect customer_id or conversion_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/wbraid from 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.search for the order_id before 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 gbraid or wbraid is present; log and skip them.
  • Centralize config: store customer_id and conversion_action_id in 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_FOUND errors.

Why Juniors Miss It

  • Assume the upload always succeeds and skip verification of the upload response.
  • Mix up click identifiers (gbraid/wbraid vs. 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.

Leave a Comment