Skip to main content
Guide

Sent vs Accepted Conversions: Finding the Gap with MCP

Six causes explain most gaps between conversions you send server-side and what Google or Meta accepts. Where each shows up, and how MCP speeds the diagnosis.

11 min read

A gap between the conversions you send server-side and the conversions an ad platform accepts or credits usually comes from one of six causes: deduplication collisions, missing click IDs, weak match quality, late uploads, rejected events, or attribution-window differences. Most leave a fingerprint in the platform's diagnostics; a booking that never carried a click ID shows up only in the sender's log. Split the gap by stage (sent, accepted, credited) to find yours. Curve, the HIPAA-compliant tracking platform with a signed BAA on every plan, logs every send with the platform's response, so the sender's record stays the source of truth while an MCP-connected assistant reads the platform side.

Split the gap into three numbers before you chase it

"Google shows fewer conversions than we sent" can be three different problems with three different owners. Every server-side conversion passes through three stages:

  • Sent. What your pipeline forwarded to the platform's conversion API. Only the sender knows this number.
  • Accepted. What the platform took without an error. An event refused for an expired click is sent but not accepted.
  • Credited. What the platform attributed to its own ads in reporting, under its own windows and counting rules.

Where the gap sits tells you which family of causes to check:

  • Sent above accepted: the platform refused the event and returned an error code saying why. Rejections, late uploads, duplicates and, on Google, unusable click IDs.
  • Accepted above credited: the platform took the event but could not tie it to an ad, or credited it to another date or action. Often no error at all, which is why these hide longest.
  • Credited above sent: a second source is reporting the same conversion, your own pipeline is sending the same Meta event twice, or the platform is crediting view-throughs and modeled conversions.

The uncomfortable part: a platform cannot report on an event it never got, so the sender's log anchors the diagnosis. Which gaps are normal is covered in comparing what your tracking sent with what Google credited; this guide is for the ones that are not.

Six causes, and where each one shows up

1. Dedup collisions: counted twice, or not at all

Deduplication fails in both directions. When credited runs above sent, a second source is usually reporting the same booking: a Meta Pixel left on the thank-you page, a Google tag nobody removed, or a booking tool's native ad integration. Meta's standard method collapses a browser event and a server event into one when event_name and event_id match exactly and both arrive within 48 hours of the first one Meta received.

It does not deduplicate server events against each other. Meta's words: "If you send us two consecutive server events with the same information, we do not discard either." A retried send, or a website Lead plus a CRM upload of the same booking, counts twice. Our Meta event ID guide covers the ID rules.

When accepted runs below sent on Google, look for CLICK_CONVERSION_ALREADY_EXISTS (same click and conversion_date_time as an existing conversion) and ORDER_ID_ALREADY_IN_USE (an order ID recorded before). A refused retry is healthy. Two different bookings refused because your "order ID" is a form ID rather than a booking reference are lost conversions.

2. Missing click IDs: sent, never tied to an ad

On Google, a conversion with no usable click ID surfaces as:

  • EVENT_NOT_FOUND: the event "could not be attributed to a click."
  • UNPARSEABLE_GCLID: Google could not decode the gclid, usually because it was truncated or altered in transit.
  • CLICK_NOT_FOUND: the hashed email or phone could not be matched to a click. Expected for leads that never came from an ad.

The causes live on the website: redirects that drop the query string, a booking tool on another domain such as IntakeQ, Calendly or Jane App, a consent banner that holds the tracking script until the URL has been rewritten, or a form that posts to a vendor page.

The tell depends on the platform. On Google, missing click IDs show up as a rising share of CLICK_NOT_FOUND or EVENT_NOT_FOUND, or as conversions that were never uploaded at all. On Meta, accepted keeps growing while credited stays flat. For the booking-tool case, Curve's bridge tokens carry attribution across the handoff so the booking still traces to the original click.

3. Match quality: accepted, but matched to no one

Meta shows an Event Match Quality score out of 10 (rated Poor, OK, Good or Great) in Events Manager for web events sent through the Conversions API. Google's enhanced conversions diagnostics (Goals, Summary, then the Diagnostics tab) raise alerts such as "No user-provided data matches." Two Google account settings look like matching problems but are not: Google refuses those uploads outright, so they sit under rejected events below.

The candid part: in healthcare, a lower match score is often the price of sending the minimum necessary. Forwarding identifiers your field mapping deliberately withholds trades a reporting gap for a disclosure, and Meta's Business Tools Terms prohibit sending health information. Fix click-ID capture first: it improves matching without adding anything about the patient.

4. Late uploads: the clock ran out

Clinic outcomes (an attended consult, a started program) land in the CRM days or weeks after the click, and both platforms enforce deadlines:

  • Meta: event_time can be up to 7 days before you send the event. If any event in a request is older, Meta returns an error "for the entire request and process no events." One stale CRM row can sink a whole batch.
  • Google: EXPIRED_EVENT means the click happened before the conversion action's click-through window, which can be set from 1 day up to 30, 60 or 90 days depending on the source (30 by default).
  • Google hard limits: Google keeps a GCLID for 90 days, and enhanced conversions for leads uploads more than 63 days after the click are not imported.
  • Google timing errors that clear on their own: TOO_RECENT_EVENT (the click was under 6 hours ago) and TOO_RECENT_CONVERSION_ACTION (the action was just created). Both should succeed on a retry after 6 hours.

5. Rejected events: configuration, not patients

These never close on their own, and they are usually one setting away from fixed:

  • An expired or revoked ad-account connection, which fails every send until someone reconnects.
  • UNAUTHORIZED_CUSTOMER: the click belongs to an Ads account the uploader cannot access, usually a manager-account mismatch.
  • CUSTOMER_NOT_ENABLED_ENHANCED_CONVERSIONS_FOR_LEADS and CUSTOMER_NOT_ACCEPTED_CUSTOMER_DATA_TERMS: an account setting is off, and Google refuses the upload until someone changes it.
  • CONVERSION_PRECEDES_EVENT: the conversion time is earlier than the click, usually a wrong timezone offset on conversion_date_time.
  • A conversion action whose status is REMOVED or HIDDEN, still receiving uploads from a mapping nobody updated.
  • ORDER_ID_CONTAINS_PII: Google refused the upload because the order ID contained personal information.

For a clinic, that last one is a privacy incident, not a tracking bug: something sent Google an identifier Google itself flagged as personal. On Meta, the Events Manager Diagnostics tab lists event issues and their fixes.

If you upload through Google's Data Manager API instead of the Google Ads API, the same failures come back as PROCESSING_ERROR_REASON_ codes (EVENT_TOO_OLD, DUPLICATE_GCLID, TOO_RECENT_CLICK, CONVERSION_PRECEDES_CLICK, INVALID_GCLID), reported as a count per reason for each request rather than as an error on each conversion.

6. Attribution windows: accepted, credited somewhere else

This is not a delivery failure, though teams assume it first. Google's standard Conversions column dates a conversion to the ad interaction that earned it; "Conversions (by conv. time)" dates it to when it happened. A booking mapped to a secondary action (include_in_conversions_metric off) appears in All conv. and not in Conversions.

Meta applies each ad set's attribution setting and can credit view-throughs. The tell for a window gap is that it shrinks or stabilizes as the period ages. One Google loss here has nothing to do with windows: uploaded conversions Google judges invalid or spam are discarded after acceptance. See choosing an attribution window, and why Meta and Google disagree for the cross-platform version.

What an MCP-connected assistant adds to the diagnosis

Every clue above lives on a different screen. Cross-referencing them is where an assistant connected over MCP earns its place.

Google Ads. Google's official MCP server is read-only. Its search tool runs GAQL, which reaches:

  • Conversion action settings: status, counting_type, click_through_lookback_window_days, include_in_conversions_metric.
  • The offline_conversion_upload_conversion_action_summary resource, whose alerts group import errors by code for the most recent full calendar day, with daily_summaries of successful, failed and pending counts for the last 7 days. For enhanced conversions for leads imports, Google points you to the enhanced conversions for leads diagnostics report in the Google Ads UI instead.
  • metrics.conversions, metrics.all_conversions and metrics.conversions_by_conversion_date per conversion action, to separate window effects from real losses.

Meta. Meta's ads MCP server is in beta. Its read tools include performance insights and signal and dataset diagnostics. It can also create campaigns and, once you confirm, start spend, so set it to read-only per asset.

Questions that shorten the hunt:

  • "For each conversion action receiving uploads, show failed and pending counts for each of the last 7 days, and the error codes in the latest day's alerts. Counts, not rows."
  • "List each conversion action's status, counting type, click-through window and whether it counts in Conversions."
  • "Compare Conversions and Conversions by conversion time for last month, per action. Where do they differ most?"

What a platform's MCP server cannot tell you is what you sent. It will find the EXPIRED_EVENT spike; it will never find the booking that was never uploaded for lack of a click ID.

How Curve keeps the sender's log as the source of truth

The other half of the diagnosis is the sender's record, and Curve builds it while forwarding. Events land on Curve's US-hosted infrastructure first, and each destination receives only the fields explicitly mapped to it, with identifiers SHA-256 hashed to the platform's requirements and a neutral event name in place of the service line.

  • Event Logs. Every send to every destination is recorded with its status and the platform's response, filterable by destination, status and event type. Google error codes sit beside the send that produced them, and an Accepted row from the Data Manager API is checked later against Google's request status. A Google conversion with no valid click ID is logged as Not Sent with that reason, so the one loss the platform can never report is a row you can filter.
  • Conversion Reconciliation. Campaign reporting shows sent, accepted and credited side by side (the dashboard labels these Curve Sent, Platform Received and Platform Attributed), with a match rate and its trend. For Google it breaks down by conversion action. For Meta the sent figure stays at platform level, because Meta uploads carry no campaign identifier.
  • Upstream fixes. Stable event IDs for Meta deduplication, no automatic resend of a Meta event whose delivery is uncertain (Meta would count the second copy), bridge tokens for booking-tool handoffs, and bulk offline conversion uploads with click-ID matching for outcomes recorded in a CRM.

Curve MCP reconciles your server-side campaigns for the assistant: it puts each campaign's platform-reported spend, clicks and impressions next to the conversions Curve's server-side tracking recorded, with cost per conversion by completed week, rounded with small groups withheld. One link opens the full sent, accepted and matched view inside Curve (Curve login required), beside Curve Analyst and Event Logs. It works with any client that can connect to an MCP server, including Claude, ChatGPT and Cursor. More in server-side campaign reconciliation in Claude.

Keep the diagnosis at the level of counts

The tempting shortcut is to paste exported failed events into a chat. Don't. Click IDs, order IDs or hashed emails for people who booked at a clinic are data about patients, and Anthropic's BAA page says data sent to third parties through MCP connectors is not covered by its BAA.

The working rule: counts by stage, error code, conversion action and week can go to the assistant. Individual events stay in Curve's Event Logs and the platform's own interface. Our piece on where MCP tool calls leak health data covers the rest.

Frequently asked questions

What is a normal gap between sent and accepted conversions?

There is no universal number, and anyone quoting one is guessing. A healthy gap is stable week to week and explained by named causes such as retries, timing errors and window lag. A gap that jumps, or never shrinks as the period ages, points to a broken pipe.

Why does Google say an upload succeeded but show no conversion?

Google's own help gives four reasons. Reporting dates a conversion to the click or impression, so check the by-conversion-time column. Processing usually takes under 12 hours but can take up to 72 for GBRAID and WBRAID-keyed conversions. A One-per-click action counts one conversion per ad interaction, and uploaded conversions judged invalid or spam are discarded.

Why does Google report more conversions than we sent?

Something besides your server-side uploads is feeding the same conversion action or column. Check for a leftover Google tag, a GA4 import, or secondary actions counted in All conv. Google's own discrepancy guidance also lists view-through conversions and cross-device modeling.

How long should we wait before judging a gap?

Three days after the period closes if any conversions are keyed to GBRAID or WBRAID, which Google uses for some iPhone traffic. Google says processing usually takes under 12 hours but up to 72 for those, and pending upload events can take up to 24 hours. Don't call a gap final while the action's click-through window is still open for that period's clicks.

Can an AI assistant fix the gap through MCP?

Mostly no. Google's official server is read-only, and most fixes live in your website, booking flow or conversion mapping, not the ad account. The assistant narrows the cause; a person changes the configuration.

Where to start

  • Pick one platform and one closed week. Write down sent, accepted and credited as absolute numbers.
  • Locate the gap by stage. Sent above accepted means error codes (on Google, including click-ID failures); accepted above credited means matching or windows.
  • Ask the platform side in one conversation. Failed and pending counts, conversion action settings, conversions by conversion time.
  • Check the sender side in the log. Tie each error code to the event type producing it, then fix the site or the mapping.
  • Repeat weekly. The weekly AI reconciliation routine turns this into a short Monday check.

To see the delivery log and reconciliation view on your own accounts, and Curve MCP answering the campaign side in an AI client, book a demo and bring the platform whose numbers you trust least. The tracking layer itself is at curvecompliance.com.

Reviewed September 2026. Error codes and limits checked against Google Ads API, Google Data Manager API and Meta Conversions API documentation as of September 24, 2026.

Stay Compliant. Scale Confidently.

Join healthcare innovators who trust Curve for HIPAA-compliant ad tracking.Launch in hours, not months. Your growth stack, now HIPAA-safe.

Book a free tracking audit