How to Connect Contact Form 7 to Google Sheets

The complete 2026 tutorial for sending CF7 form data directly to Google Sheets - without Zapier, without GSheetConnector, and without per-submission fees.

Last updated: 2026-03-13 8 min read

TL;DR

Install SheetLink Forms, deploy a Google <a href="/docs/google-sheets-setup">Apps Script</a> webhook to your Sheet, paste the URL into the plugin settings, map your CF7 form tags (like [your-name] and [your-email]) to columns, and test. The entire process takes about 5 minutes. No Zapier, no OAuth tokens, no monthly fees.

Contact Form 7 is the most-installed WordPress form plugin - over 5 million active installs and counting. It's free, open source, and maintained by Takayuki Miyoshi. But CF7 has always had one glaring limitation: it doesn't store submissions anywhere by default. Every entry is sent as an email, and if that email fails or gets filtered, the data is gone.

CF7 users have historically solved this with three patterns: bolt-on storage (the Flamingo plugin), manual copy-paste from email notifications, or a paid middleware subscription like Zapier. Each has friction. Flamingo stores entries inside wp_posts - a fragile place for business-critical data. Zapier charges $29.99/month and up, per form submission. GSheetConnector works but relies on OAuth tokens that expire silently and need periodic reauthorization.

SheetLinkWP takes a different approach. It connects CF7 directly to Google Sheets through a lightweight Apps Script webhook - no middleware, no OAuth tokens stored in your WordPress database, and no per-submission fees. Your form data flows from CF7 straight into a spreadsheet you own. This guide walks through the complete setup, explains the CF7-specific quirks (form tag syntax, special mail tags, acceptance fields, conditional fields), and shows the real-world configurations CF7 users actually need.

Why Send CF7 Submissions to Google Sheets

CF7's email-only delivery model breaks down the moment your form becomes important. A missed spam-filtered notification is a lost lead. An inbox search is a poor substitute for sortable, filterable data. And teams larger than one person need a shared source of truth - not a forwarded email thread.

Google Sheets fills that gap for most small businesses. It's free, collaborative, sortable, and already familiar. You can build pivot tables, share with specific people, connect to Google Looker Studio for dashboards, or export to CSV for your CRM. Form-to-Sheets isn't a workaround - for thousands of sites, it's the permanent system of record.

The catch: CF7 has no native Sheets connection, so you have to bridge them somehow. SheetLinkWP is purpose-built for that bridge. It reads CF7's form tags (including special mail tags like [_remote_ip] and [_serial_number]), formats them cleanly, and writes a new row to your Sheet - synchronously, with a retry queue if Google is slow to respond.

How SheetLinkWP Delivers CF7 Data to Google Sheets

SheetLinkWP intercepts the CF7 submission event, serializes every form tag (plus any UTM parameters and click IDs you've enabled), and POSTs a JSON payload to an Apps Script endpoint deployed inside your own Google account. Here's the exact flow:

  1. 1. Visitor submits form: CF7's standard submission handler fires via the wpcf7_mail_sent and wpcf7_before_send_mail hooks. SheetLinkWP listens on both, so data is captured even if you disable email sending entirely.
  2. 2. Field collection: SheetLinkWP reads every posted field (form tags, hidden fields, acceptance checkboxes, file upload filenames) plus metadata: submission timestamp, IP address, user agent, referer, and the URL the form was submitted from.
  3. 3. UTM + click ID capture: If enabled, SheetLinkWP reads utm_source, utm_medium, utm_campaign, utm_term, utm_content from the referring URL (or a cookie if you use cross-page attribution) and GCLID/fbclid/msclkid from ad clicks.
  4. 4. Field mapping applied: Your mapping configuration translates CF7 tag names to Sheet column positions. Unmapped fields are dropped; mapped-but-empty fields write an empty cell.
  5. 5. Webhook POST to Apps Script: A JSON payload is POSTed to your Apps Script web app URL. The script appends a new row to your destination Sheet.
  6. 6. Retry on failure: If the webhook times out or returns a non-2xx response, SheetLinkWP queues the payload in a WordPress transient and retries with exponential backoff (30s, 60s, 2min, 5min, 15min). No submission is lost to transient Google outages.

What You Need

  • A WordPress site with Contact Form 7 installed and at least one form created
  • A Google account with access to Google Sheets
  • SheetLink Forms plugin (free tier works, or any paid license)

Step-by-Step Setup

Field mapping tip: CF7 uses form tags like [your-name], [your-email], [your-subject]. In SheetLinkWP's field mapping, use the tag name without brackets. Special mail tags are also supported: _date (submission date), _time (submission time), _remote_ip (visitor IP), _serial_number (auto-increment ID), _post_title, and _post_url.
  1. 1

    Create your destination Google Sheet

    Open Google Sheets and create a new blank spreadsheet. Name it something descriptive like "CF7 Leads - March 2026". You don't need to add column headers - SheetLinkWP creates them automatically when the first submission arrives. If you prefer to set headers manually, add them in row 1 matching your CF7 field names: Name, Email, Phone, Message, etc.

  2. 2

    Deploy the Apps Script webhook

    In your Google Sheet, click Extensions > Apps Script. Delete any existing code in the editor. Paste the SheetLinkWP receiver script (provided in the SheetLink Forms plugin under SheetLink > Settings > Setup Guide). Click Deploy > New deployment. Under "Select type", choose "Web app". Set "Execute as" to yourself and "Who has access" to "Anyone". Click Deploy and authorize the permissions when prompted. Copy the web app URL - you'll need it in the next step.

  3. 3

    Install and activate SheetLink Forms

    If you haven't already, download SheetLink Forms from sheetlinkwp.com (or install the free version from WordPress.org). Go to Plugins > Add New > Upload Plugin, select the ZIP file, and click Install Now. Activate the plugin. You'll see a new "SheetLink" menu item in your WordPress admin sidebar.

  4. 4

    Paste the webhook URL

    Navigate to SheetLink > Settings in your WordPress admin. Paste the Apps Script web app URL you copied in Step 2 into the "Webhook URL" field. Click Save. SheetLink will test the connection and show a green checkmark if the webhook is reachable.

  5. 5

    Map your CF7 form fields

    Go to SheetLink > Field Mapping. Select "Contact Form 7" as your form plugin, then choose your specific form from the dropdown. SheetLinkWP will auto-detect your CF7 form tags. Map each tag to a Google Sheets column - for example, map "your-name" to column A, "your-email" to column B. CF7 uses tag names without brackets: [your-name] becomes "your-name" in the mapping. Special mail tags like [_date], [_time], and [_remote_ip] are also available.

  6. 6

    Enable UTM and metadata capture (optional)

    In the field mapping screen, toggle on "UTM Parameters" to automatically capture utm_source, utm_medium, utm_campaign, utm_term, and utm_content from the page URL. Toggle on "Click IDs" to capture GCLID (Google Ads), fbclid (Facebook), and msclkid (Microsoft Ads). These fields are appended as additional columns to every row.

  7. 7

    Test the connection

    Open your website's front end and submit a test entry through your CF7 form. Within 2-3 seconds, check your Google Sheet - you should see a new row with all the mapped data. If the row doesn't appear, check SheetLink > Delivery Log for error details. Common issues: the webhook URL was copied with trailing whitespace, or the Apps Script deployment needs re-authorization.

Contact Form 7 Field Reference

CF7 uses a form tag syntax like [text* your-name] or [email* your-email]. SheetLinkWP reads the tag name (the portion after the type) as the field key. Here are the CF7 tags and special mail tags you can map to Sheet columns:

Field key Source Notes
your-name CF7 text tag Standard CF7 default name field. Any [text] or [text*] tag.
your-email CF7 email tag Validated as email by CF7. Failed validation submissions never reach SheetLinkWP.
your-subject CF7 text tag Default subject field in CF7's starter form.
your-message CF7 textarea tag Default message field. Can be long - SheetLinkWP writes up to 50,000 characters per cell.
menu-nnn CF7 select dropdown Dropdown menu selections. Multiple-select menus write comma-separated values.
checkbox-nnn CF7 checkbox group Multiple checked values join with commas. Unchecked = empty cell.
radio-nnn CF7 radio group Single selected value.
acceptance-nnn CF7 acceptance tag Writes "accepted" or empty. Useful for GDPR consent logging.
file-nnn CF7 file upload Writes the original filename. If you enable Drive sync in the add-on, this becomes a Drive URL.
_date Special mail tag Submission date in site timezone (YYYY-MM-DD).
_time Special mail tag Submission time in site timezone (HH:MM:SS).
_serial_number Special mail tag Auto-incrementing submission ID. Unique per form.
_remote_ip Special mail tag Visitor IP. Respects CF7's privacy masking if configured.
_user_agent Special mail tag Browser user agent string. Useful for mobile/desktop segmentation.
_url Special mail tag Full URL the form was submitted from (includes query string - UTMs included).
_post_title Special mail tag Title of the WP post/page containing the form. Useful when the same form is embedded on multiple pages.
_post_id Special mail tag Numeric post ID. Pair with _post_title for fast filtering.
_user_email Special mail tag Logged-in user's email (empty for guest submissions). Only populated if CF7 detects an authenticated user.

Real-World Use Cases

Replacing Flamingo with a searchable Sheet

Flamingo is the de facto CF7 entry storage plugin, but entries live inside wp_posts and wp_postmeta - unindexed for full-text search, slow on sites with thousands of entries, and invisible to non-WP users. Pointing CF7 at a Google Sheet gives you instant sort/filter, shareable URLs, Google Looker Studio compatibility, and no database bloat.

Field mapping: Map your-name, your-email, your-subject, your-message, _date, _time, _remote_ip, _post_title. Leave Flamingo active during the first week as a backup.

GDPR-compliant consent logging

Many jurisdictions require you to log affirmative consent at submission time (what was agreed to, when, and by whom). CF7's [acceptance] tag handles the checkbox, but storing the consent trail is on you. A Sheet gives you an audit-ready row per submission.

Field mapping: Map your-email, acceptance-privacy (writes "accepted"), acceptance-marketing, _date, _time, _remote_ip, _url. Keep the Sheet export-only; never delete rows (use a "withdrawn" column instead).

Multi-language (WPML / Polylang) sites

When the same form exists in English and Spanish, submissions arrive with identical field names but different page contexts. Mapping _post_title and _url lets you filter which language generated the lead without duplicating form logic.

Field mapping: Map standard CF7 tags plus _url and _post_title. Add a Google Sheets formula column: =IF(ISNUMBER(SEARCH("/es/", F2)), "Spanish", "English").

Marketing attribution for CF7 lead forms

You're running Google Ads, Facebook Ads, and organic search to the same landing page. Without UTMs captured at submission, you can't tell which channel produced a lead. SheetLinkWP's built-in UTM capture appends five attribution columns automatically - no custom form fields required.

Field mapping: Standard CF7 tags + SheetLinkWP's automatic columns: utm_source, utm_medium, utm_campaign, utm_term, utm_content, gclid, fbclid, msclkid. Enable both UTM Parameters and Click IDs toggles.

Advanced Tips

Coexist with Flamingo during migration

Don't deactivate Flamingo the day you set up SheetLinkWP. Run both in parallel for two to four weeks. Compare Sheet rows against Flamingo entries daily - if every Flamingo entry has a corresponding row in your Sheet, you're safe to disable Flamingo's storage. This dual-write approach catches edge cases (spam-filtered submissions, redirected forms) before you lose any data.

CF7 Conditional Fields work automatically

If you use the popular CF7 Conditional Fields plugin, SheetLinkWP receives only the fields that were actually shown and filled. Hidden conditional fields write empty cells. To detect which branch a user took, map a sentinel field (like a hidden [text] with a default value set by JavaScript when the branch is chosen).

Disable email entirely and rely on Sheets

CF7 won't break if you leave the mail section empty - submissions still fire and SheetLinkWP still writes to your Sheet. For sites where deliverability is unreliable (low-sender-reputation hosts), this is more reliable than email. Pair with Sheet-based notifications: a Google Apps Script trigger on new rows can send a Slack message or an email through Google's own infrastructure.

File upload URLs instead of filenames

By default, [file] tag values write the original filename (e.g., resume.pdf). With the SheetLinkWP Drive add-on, uploads are streamed to a designated Drive folder and the Sheet cell becomes a clickable URL. This is the non-storage-heavy way to keep a full submission archive - no uploads directory backups required.

Handle [select multiple] cleanly

When a [select] tag has the multiple attribute, CF7 submits an array. SheetLinkWP joins with commas by default. If your downstream workflow needs an exact match on one value, switch to a separate [checkbox] group where each option is its own column (map checkbox-interest:newsletter to column K, checkbox-interest:demo to column L, etc.).

Troubleshooting

Submissions aren't appearing in Google Sheets

Check SheetLink > Delivery Log for error messages. The most common cause is a stale Apps Script deployment. Re-deploy the web app (create a new deployment, don't edit the existing one) and update the URL in SheetLink settings.

Some fields are missing or in the wrong columns

Open SheetLink > Field Mapping and verify each CF7 tag is mapped to the correct column. Remember: CF7 tags are case-sensitive. [Your-Name] and [your-name] are different tags.

UTM parameters are blank

UTM values are captured from the page URL at the time of submission. Test by adding ?utm_source=test&utm_medium=test to your form page URL before submitting. If still blank, ensure "UTM Parameters" is toggled on in field mapping.

[acceptance] checkbox field writes nothing

CF7's acceptance tag has unusual behavior: if the checkbox is optional (<code>[acceptance consent optional]</code>), the field key isn't submitted at all when unchecked. SheetLinkWP writes an empty cell. For GDPR audit trails, set the acceptance tag without the optional flag so the submission fails if unchecked - then you only ever log positive consent.

Serial numbers skip or duplicate across forms

CF7's <code>[_serial_number]</code> is per-form, not global. If you have two forms both mapping _serial_number to the same Sheet column, you'll see overlapping numbers. Either keep each form in its own tab, or map <code>_post_id</code> alongside for unambiguous identification.

Japanese/Chinese characters show as ???

This is a character encoding mismatch. CF7 emits UTF-8 by default. If your Apps Script was created from an older template, it may default to WINDOWS-1252. Redeploy the receiver from the current SheetLinkWP setup guide - the current version forces UTF-8 explicitly.

CF7 to Google Sheets: SheetLinkWP vs Alternatives

FeatureGSheetConnectorZapierSheetLinkWP
Auth method OAuth 2.0 (tokens expire)OAuth 2.0 via ZapierApps Script webhook (no tokens)
Monthly cost (500 subs) Free / $49 yr Pro$29.99+/mo$0 (one-time $39)
Per-submission fee NoYes ($0.01-0.03/task)No
Retry on failure No built-in retryAuto-retryBuilt-in retry queue
UTM capture NoExtra stepsAutomatic
Conditional routing NoMulti-path ZapBuilt-in
Setup time ~10 minutes~10 minutes~5 minutes
Data passes through Google APIZapier serversDirect to Google (no middleware)

Frequently Asked Questions

Does SheetLinkWP work with Contact Form 7?

Yes. SheetLinkWP supports Contact Form 7 natively, including all standard form tags, special mail tags, conditional fields, and file upload metadata.

Do I need to replace GSheetConnector?

If you're happy with GSheetConnector, you don't have to switch. The main advantages of SheetLinkWP are: no OAuth tokens (so no silent failures from expired tokens), built-in retry queue, UTM/click ID capture, and conditional routing - all features GSheetConnector lacks.

Can I send different CF7 forms to different Google Sheets?

Yes. SheetLinkWP's conditional routing lets you map each CF7 form to a different Sheet or tab. You can also route based on field values - for example, send leads from a pricing form to one Sheet and support requests to another.

Is CF7's free version sufficient, or do I need a premium add-on?

The free version of Contact Form 7 works perfectly with SheetLinkWP. No premium CF7 add-ons are required.

What happens if Google Sheets is temporarily down?

SheetLinkWP's retry queue caches the submission locally and retries with exponential backoff (30s, 60s, 2min, 5min, 15min). Submissions are preserved and retried automatically.

How much does SheetLinkWP cost for CF7 users?

The free tier supports 1 site with basic form-to-Sheets delivery. Paid licenses start at $39 (one-time, lifetime) for the Freelancer tier with all 12 form integrations, retry queue, UTM capture, and conditional routing.

Will this slow down form submissions for users?

No. The webhook POST to Apps Script completes in 200-500ms in typical conditions, and CF7's submission handler doesn't block on it - the user's form success message appears immediately. If Apps Script is slow, SheetLinkWP queues the row in a WordPress transient and retries in the background.

Can I use this alongside Flamingo?

Yes. Flamingo and SheetLinkWP operate on separate CF7 hooks and don't interfere. Many sites run both in parallel: Flamingo as local backup, Sheets as the working dataset. This is the recommended migration path for the first 2-4 weeks.

Does SheetLinkWP support CF7 Conditional Fields?

Yes. Only fields shown and filled during submission are written to the Sheet. Hidden conditional branches produce empty cells. To detect which branch a user took, add a hidden sentinel field set by JavaScript when the branch is chosen.

What happens with [file] upload fields?

By default SheetLinkWP writes the filename. With the optional Drive add-on, uploads are copied to a designated Google Drive folder and the cell becomes a clickable URL. The uploaded file stays in your WordPress uploads folder for standard CF7 email delivery - Drive sync is additive, not a replacement.

Is CF7's form data encrypted in transit to Google?

Yes. The Apps Script web app URL is always HTTPS, and SheetLinkWP enforces TLS on the outbound request. Payload encryption in transit is managed by Google's infrastructure - the same standard that protects your Sheets UI sessions.

Related How-To Guides

Connect Contact Form 7 to Google Sheets in 5 Minutes

One plugin. No OAuth tokens. No per-submission fees. Works with CF7 and 6 other form builders.