Skip to main content
Contact Form 7 → Google AdsIntegration guide

Connecting Contact Form 7 to Google Ads

Contact Form 7 is free, everywhere, and stores nothing by default — which is the whole problem. Google Ads knows what you spent and which click it came from, and nothing at all about what happened afterwards. The join between them succeeds or fails on one thing: whether the GCLID reaches the Contact Form 7 submission before the conversion happens, because Google Ads can only match a conversion it can tie back to a click it recognizes.

Free30 minutesNo obligation

Specific to this pair

Contact Form 7 to Google Ads: gclid in a hidden field, not the cache

Store the gclid in a hidden Contact Form 7 field filled by JavaScript from a first-party cookie, never in PHP, because page caching bakes one visitor's gclid into every lead. Upload qualified leads to an import-type Google Ads action within 90 days, use Enhanced Conversions for leads without a gclid, and upload only post-spam-filter submissions.

Google Ads needs the gclid stored with the submission, which on Contact Form 7 means a hidden field. The safe way is to fill it with JavaScript from a first-party cookie after the page loads. Filling it in PHP when the page renders breaks on any WordPress site with page caching: the first visitor's gclid is baked into the cached HTML and every later lead carries it. Check stored submissions for repeated gclid values before trusting a single upload.

CF7 leads are rarely worth the same, so a raw submission is a weak bidding signal. The better pattern is to store each lead with its gclid and email, then upload to an import-type conversion action once the lead is marked qualified, within 90 days of the click. Enhanced Conversions for leads covers submissions where the gclid is missing, matching on the hashed email the visitor typed into the form.

Watch spam. Contact Form 7 has no CAPTCHA unless you add one, and a submission flood uploaded as conversions trains Smart Bidding on bots. Upload only from submissions that reached wpcf7_mail_sent after your spam filter, and keep a raw-submission action, if you want one at all, set to secondary so it reports without steering bids.

Contact Form 7 → Google Ads · what breaks

Why this join usually fails — Contact Form 7 → Google Ads

  1. 01

    The GCLID never reaches Contact Form 7

    There is no entries table to write to, so the identifier has to be captured into a hidden field and persisted by whatever you add for storage. Contact Form 7 submits over AJAX, so the page does not reload and anything expecting a navigation event never fires.

  2. 02

    AJAX submission means no page load to hook

    Setups that fire a conversion on thank-you-page load simply never fire. Setups that listen for the DOM event miss anyone whose script execution was blocked or deferred.

  3. 03

    The conversion action is the wrong type

    Uploads against a standard website conversion action fail. The action has to be created as 'Import' — and existing actions cannot be converted, so this is discovered late and requires starting a new action with no history.

  4. 04

    Nothing reconciles afterwards

    Google Ads reports uploads in Goals → Conversions → Uploads, with rows accepted and rows failed. A green result means the file parsed, not that the clicks matched. The number to watch is how many conversions actually appear against campaigns afterwards.

Contact Form 7 → Google Ads · the fix

What working looks like — Contact Form 7 → Google Ads

  • The GCLID on every submission

  • Conversions arriving in Google Ads

    Conversions appear against the campaign, ad group and keyword that produced the click, with the value you sent — which is what lets Smart Bidding optimize toward revenue instead of toward form fills.

  • Reconciled against the source

Contact Form 7 → Google Ads · architecture

How Contact Form 7 and Google Ads actually connect

  1. 1

    Contact Form 7 holds the truth

    Out of the box Contact Form 7 emails the submission and keeps no record. Before any attribution work is meaningful, submissions have to be stored somewhere queryable. That is step one and it is not optional.

  2. 2

    Google Ads needs a click to match

    Google Ads matches an uploaded conversion back to a click using the GCLID. The conversion action must be created as an import type — an upload against a website-tag conversion action is rejected. Uploads must also land inside Google's window: the click has to be within the last 90 days.

  3. 3

    The identifier is the bridge

    The GCLID, captured at the visit and carried into the Contact Form 7 submission.

  4. 4

    The event source decides reliability

    Fire server-side from PHP. The browser-side wpcf7mailsent DOM event exists and is commonly used, but it depends on the visitor's browser executing correctly and on the AJAX response arriving — the server hook does not.

  5. 5

    Deduplication at the destination

    Google deduplicates on the combination of GCLID, conversion action and conversion time. Uploading the same click twice against the same action at the same timestamp is rejected rather than double-counted, but uploading it against a second conversion action counts twice — which is how most double-counting here actually happens.

Contact Form 7 → Google Ads · normal or broken

Working vs. broken, side by side — Contact Form 7 → Google Ads

Normal, not a fault

  • The GCLID present on the submission

  • Sent from the wpcf7_mail_sent hook

  • Deduplicated correctly

    Google deduplicates on the combination of GCLID, conversion action and conversion time. Uploading the same click twice against the same action at the same timestamp is rejected rather than double-counted, but uploading it against a second conversion action counts twice — which is how most double-counting here actually happens.

  • Reconciles with the source

Actually broken

  • The GCLID missing on most records

    There is no entries table to write to, so the identifier has to be captured into a hidden field and persisted by whatever you add for storage. Contact Form 7 submits over AJAX, so the page does not reload and anything expecting a navigation event never fires.

  • Sent from the browser

    Setups that fire a conversion on thank-you-page load simply never fire. Setups that listen for the DOM event miss anyone whose script execution was blocked or deferred.

  • Counted twice, or not at all

    Uploads against a standard website conversion action fail. The action has to be created as 'Import' — and existing actions cannot be converted, so this is discovered late and requires starting a new action with no history.

  • Nobody has reconciled it

Contact Form 7 → Google Ads · diagnose

Diagnostic order — Contact Form 7 → Google Ads

  1. 01

    Count submissions carrying the GCLID

  2. 02

    Follow one real conversion end to end

  3. 03

    Confirm submissions are being stored at all

    If the only record is an email inbox, there is nothing to reconcile and no way to prove any number. Fix storage before touching attribution.

  4. 04

    Check the conversion action type and the upload diagnostics

    In Google Ads, Goals → Conversions → Uploads shows every upload with its error rows. Read the errors rather than the success count; a file can import successfully with most rows rejected.

  5. 05

    Read the match rate, not the success message

    Google Ads reports uploads in Goals → Conversions → Uploads, with rows accepted and rows failed. A green result means the file parsed, not that the clicks matched. The number to watch is how many conversions actually appear against campaigns afterwards.

Contact Form 7 → Google Ads · prove

How it gets proven — Contact Form 7 → Google Ads

Source of truth

Whatever you configure to persist submissions — an entries plugin, or your own database table. By default there is nothing to reconcile against.

  • The GCLID confirmed present on a live submission.
  • The Uploads diagnostics read row by row, with the accepted count reconciled against conversions appearing in campaign reporting.
  • Stored submissions confirmed to match the email record for the same period, before any attribution claim is made.

Contact Form 7 → Google Ads · free audit

What we check in the free audit

  • Count submissions carrying the GCLID
  • Follow one real conversion end to end
  • Confirm submissions are being stored at all
  • Check the conversion action type and the upload diagnostics
  • Read the match rate, not the success message

Checked against

Whatever you configure to persist submissions — an entries plugin, or your own database table. By default there is nothing to reconcile against.

Get my free conversion tracking audit

Free30 minutesNo obligation

Contact Form 7 → Google Ads · when not to buy

When you don't need this — Contact Form 7 → Google Ads

  • Measure identifier coverage yourself first — pull your last hundred submissions and count how many carry the GCLID.
  • If you are on Contact Form 7 and serious about attribution, moving to a form plugin that stores entries is often cheaper than working around the one that does not. We will say so rather than bill for the workaround.
  • If your sales close inside a few days and your website tag already reports accurately, you may not need offline import at all. It exists to solve the delay between click and revenue.

Contact Form 7 → Google Ads · what we deliver

What gets built — Contact Form 7 → Google Ads

  • Identifier capture into Contact Form 7

    Hidden field populated from a first-party cookie, plus a storage layer so the submission and its identifier survive past the email. The wpcf7_before_send_mail hook is where both happen.

  • Event source: the wpcf7_mail_sent hook

    Fire server-side from PHP. The browser-side wpcf7mailsent DOM event exists and is commonly used, but it depends on the visitor's browser executing correctly and on the AJAX response arriving — the server hook does not.

  • Dispatch to Google Ads

    Offline Conversion Import through the Google Ads API, or a scheduled upload. Enhanced conversions for leads where GCLID coverage is poor and you have consented email addresses.

  • Reversals where they exist

    Nothing to reverse. Spam filtering before the send is the equivalent concern.

Written guarantee

95%+ tracking accuracy

Measured against Whatever you configure to persist submissions — an entries plugin, or your own database table. By default there is nothing to reconcile against.. Miss it and we keep working at no cost.

Get my free conversion tracking audit

From $400 · See packages

FAQ

Contact Form 7 → Google Ads questions, answered

Add a hidden field, populate it with JavaScript from a cookie set on landing, and store the submission somewhere queryable, since CF7 keeps nothing itself. Avoid filling the field in PHP if the page is cached.

Free · 30 min

Get Contact Form 7 and Google Ads joined properly

Free30 minutesNo obligation