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
- 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.
- 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.
- 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.
- 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
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
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
The identifier is the bridge
The GCLID, captured at the visit and carried into the Contact Form 7 submission.
- 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
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
- 01
Count submissions carrying the GCLID
- 02
Follow one real conversion end to end
- 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.
- 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.
- 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.
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.
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.
Only if every submission is worth roughly the same. Otherwise upload qualified leads as offline conversions and keep raw submissions as a secondary action.
Almost always because the GCLID never reached the Contact Form 7 submission. 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. Measure coverage before debugging the dispatch.
The GCLID — the click ID Google appends to your landing page URL when auto-tagging is on. For iOS App campaigns and some Shopping traffic you will see GBRAID or WBRAID instead, and those behave differently: WBRAID cannot be used with user-provided data in the same way, and neither joins to an individual user. Enhanced conversions for leads is the alternative path, matching on hashed email or phone rather than a click ID, and it is the right choice when GCLID coverage is poor.
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.
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.
More on Contact Form 7 → Google Ads
- Contact Form 7 + GoogleGoogle Ads and GA4 tracking for Contact Form 7
- Contact Form 7 → Microsoft AdsConnecting Contact Form 7 to Microsoft Ads
- Contact Form 7 → Apple Search AdsConnecting Contact Form 7 to Apple Search Ads
RELATED GUIDES
Where Contact Form 7 → Google Ads fits in the rest of your tracking
- Google Ads · Home servicesGoogle Ads conversion tracking for home service businesses
- Google Ads · Law firmsGoogle Ads conversion tracking for law firms
- Google Ads × CRM DealsHow to reconcile Google Ads against your CRM's closed-won deals
- Google Ads · Lead magnet → saleHow to track lead magnet to sale for Google Ads
- Paperform → Google AdsConnecting Paperform to Google Ads
- Contact Form 7 → NextdoorConnecting Contact Form 7 to Nextdoor Ads
- Law firmsConversion tracking for law firms, without sending case details anywhere
- Typeform → Google AdsConnecting Typeform to Google Ads
Free · 30 min
Get Contact Form 7 and Google Ads joined properly
Free30 minutesNo obligation
