Contact Form 7
Connect Contact Form 7 with WPsigner to collect legally binding signatures from CF7 submissions. You can either sign the form content inline (recommended) or create documents from a WPsigner PDF template via a feed.
How It Works
Section titled “How It Works”| Component | Description |
|---|---|
| WPsigner Signing tag | CF7 form-tag [insigner_signing] with Draw / Type / Upload + optional OTP |
| Content signing | Builds a signed PDF from the submission + signature (no template required) |
| Feed | Optional rules for CC, title, template mode, mappings, extra signers, auto-send |
| Merge tags | {inSigner:signed_pdf_url} and {inSigner:download_button} in CF7 Mail / success message |
| Auto-send | Template mode only — emails the remote signing link after the document is created |
Processing runs on CF7’s wpcf7_before_send_mail hook (not wpcf7_mail_sent). That means:
- The signed PDF is ready before CF7 sends its email, so merge tags work in the same message
- Document creation does not depend on SMTP succeeding
- If signing or a required feed fails, WPsigner sets CF7’s
$abortflag so the form submission does not complete with a half-built document
Two Ways to Sign
Section titled “Two Ways to Sign”| Mode | Best for | Requires template? | Requires feed? |
|---|---|---|---|
| Content signing | Applications, consents, agreements built from form answers | No | No (feed optional) |
| Template + feed | Fixed PDF contracts (NDA, lease, offer letter) | Yes | Yes |
If the form contains an [insigner_signing] tag, WPsigner always uses content signing for that submission. Template feeds on the same form are skipped. In the feed UI, selecting a form that already has a Signing tag switches the modal to inline options (signature field + CC) and hides template / mappings / additional signers / auto-send.
Content Signing (Recommended)
Section titled “Content Signing (Recommended)”Generate a signed PDF from the form submission content plus an inline signature. WPsigner builds the PDF automatically — you do not upload a template.
How It Works
Section titled “How It Works”User submits CF7 form ↓CF7 validates fields (+ reCAPTCHA / Akismet / honeypot as configured) ↓wpcf7_before_send_mail ↓WPsigner validates signature (+ OTP if required) ↓PDF generated from answers → signature applied → Certificate of Completion ↓Merge tags primed → CF7 Mail / success message can include the download link- Install and activate Contact Form 7 and WPsigner (v3.0.3.2+ recommended for full CF7 parity)
- Open Contact → Contact Forms → Edit
- Add at least:
- A name field (e.g.
[text* your-name]) - An email field (e.g.
[email* your-email]) - The WPsigner Signing tag (see tag syntax)
- A name field (e.g.
- In Mail / Mail (2), optionally add merge tags (see Merge tags)
- Save the form and publish it on a page with the CF7 shortcode
When a visitor submits:
- WPsigner captures the signature and form rows
- A completed PDF is generated with audit trail and Certificate of Completion
- Secure download URLs are available via merge tags
- WPsigner can send its own completion notification according to your email settings
Optional Feed (CC, Custom Title)
Section titled “Optional Feed (CC, Custom Title)”Feeds are optional for content signing. Create one only if you need:
- CC emails on the signed document
- A custom document title
- An explicit Signing field name (when the form has more than one)
- WPsigner → Integrations → Contact Form 7 → New Feed
- Select a CF7 form that includes a Signing tag
- Configure CC / title / signature field as needed
- Save the feed
Without a feed, WPsigner builds an automatic content-signing feed (auto) with:
- Title:
{form title} - {{signer_name}} - Signature field: first valid signature submitted
- Name / email: auto-detected from common CF7 tags
- Owner: see Document owner
Submission Failure Behavior
Section titled “Submission Failure Behavior”If content signing fails (invalid signature, OTP missing/expired, PDF error, rate limit, etc.), WPsigner aborts the CF7 mail pipeline ($abort = true). The visitor sees a CF7 error instead of a “success” email without a document. Partial documents are cleaned up.
WPsigner Signing Tag
Section titled “WPsigner Signing Tag”Insert with the Tag Generator
Section titled “Insert with the Tag Generator”- Edit the CF7 form
- Open the tag generator and choose WPsigner Signing
- Configure:
- Required (recommended)
- Field name (default
signature) - OTP method (Disabled / Email / SMS / Email+SMS / WhatsApp — available methods depend on Twilio / WhatsApp setup)
- Signer email field (default
your-email) - Label (default
Signature)
- Insert the generated tag into the form template
Works with CF7 Tag Generator v2 (data-tag-option for otp:, email:, label:) and the classic generator fallback.
Tag Syntax
Section titled “Tag Syntax”| Form | Meaning |
|---|---|
[insigner_signing name] | Optional signing field |
[insigner_signing* name] | Required signing field |
otp | Require OTP (default method: email) |
otp:email | OTP by email |
otp:sms | OTP by SMS (Twilio required) |
otp:both | OTP by email + SMS (Twilio required) |
otp:whatsapp | OTP by WhatsApp (WhatsApp integration required) |
email:your-email | CF7 tag name used as the signer / OTP email |
label:Signature | Visible label (_ becomes a space) |
Examples
Section titled “Examples”[insigner_signing* signature]
[insigner_signing* signature otp:email email:your-email]
[insigner_signing* signature otp:sms email:your-email label:Firma]
[insigner_signing* signature otp:whatsapp email:work-email label:Authorized_Signature]If a content-signing feed is active for the same form, the feed’s Signer Email Field overrides the tag’s email: option for OTP delivery when the feed targets that signature field (or uses auto-detect).
Frontend Experience
Section titled “Frontend Experience”The field renders a shared signature pad:
| Tab | Behavior |
|---|---|
| Draw | Stylus / mouse pad (colors: black, blue, navy) |
| Type | Typed signature with script fonts |
| Upload | PNG/JPG upload (converted to a PNG data URI) |
If OTP is enabled:
- User completes the signature
- OTP panel appears (Identity verification)
- User requests a 6-digit code, enters it, and verifies
- Submit is blocked until the signature and OTP token are present
On successful CF7 reset / resubmit, the pad and OTP state clear.
Assets load automatically when the tag is present (wps-signature-pad, wps-cf7-signature, wps-cf7-form-otp).
OTP Verification
Section titled “OTP Verification”Methods
Section titled “Methods”| Method | Requirements |
|---|---|
Email field on the form (email: option or auto-detect) | |
| SMS | Phone on the form + Twilio configured |
| Email + SMS | Email + phone + Twilio |
| Phone + WhatsApp Business configured |
Phone numbers should use international E.164 format (example: +15551234567).
Behavior
Section titled “Behavior”- 6-digit code, expires in 10 minutes, max 5 verify attempts
- Session binding uses a secure browser cookie (
HttpOnly,SameSite=Strict) — not the client IP (works behind proxies / CDNs) - OTP context is scoped to CF7 + form ID (isolated from Fluent Forms / other builders)
- On successful content signing the OTP proof is consumed (one-time use)
- Phone used for SMS/WhatsApp is bound into the OTP token for integrity
AJAX Endpoints (troubleshooting)
Section titled “AJAX Endpoints (troubleshooting)”| Action | Auth | Nonce |
|---|---|---|
wps_cf7_send_otp | Logged-in + guests | wps_public_nonce |
wps_cf7_verify_otp | Logged-in + guests | wps_public_nonce |
OTP Rate Limits
Section titled “OTP Rate Limits”| Action | Scope | Limit |
|---|---|---|
| Send | Per form + IP | 15 / 5 minutes |
| Send | Per form + email + IP | 5 / 1 minute |
| Verify | Per form + IP | 30 / 5 minutes |
| Verify | Per form + email + IP | 10 / 1 minute |
The CF7 form must be published. Draft forms reject OTP requests.
Merge Tags in CF7 Emails
Section titled “Merge Tags in CF7 Emails”Use these tags in CF7 Mail, Mail (2), and the messages that CF7 displays after submit:
| Tag | Output |
|---|---|
{inSigner:signed_pdf_url} | Secure URL to download the completed signed PDF |
{inSigner:download_button} | HTML button (“Download Signed PDF”) in HTML mail bodies; plain URL in subjects / non-HTML contexts |
Example (Mail body, HTML)
Section titled “Example (Mail body, HTML)”<p>Thank you. Your signed document is ready:</p><p>{inSigner:download_button}</p><p>Or open this link: {inSigner:signed_pdf_url}</p>Where tags are replaced
Section titled “Where tags are replaced”| Surface | Mechanism |
|---|---|
| Mail subject, body, additional headers | wpcf7_mail_components |
| On-screen success / error messages | wpcf7_display_message |
The Signing field itself never dumps base64 into email: the mail tag is replaced with the text Signed.
Download links use WPsigner’s secure expiring download URLs for the completed PDF (Certificate of Completion included in the completed package).
Template + Feed Mode
Section titled “Template + Feed Mode”Use this when you have a fixed PDF template with pre-placed signature fields and the form does not include [insigner_signing].
How It Works
Section titled “How It Works”User submits CF7 form (no Signing tag) ↓wpcf7_before_send_mail ↓Matching template feeds run ↓Document created from template + mappings ↓(Optional) Auto-send signing emails to primary + additional signersPrerequisites
Section titled “Prerequisites”- WPsigner v3.0.3.2+ (recommended)
- Contact Form 7 active
- A CF7 form with name + email tags
- A WPsigner Template with signature fields positioned
Create a Template
Section titled “Create a Template”- WPsigner → New Document → upload PDF
- Add a placeholder signer
- Place Signature / Name / Email / Date / Text fields
- Save as Template
Create a Feed
Section titled “Create a Feed”- WPsigner → Integrations → Contact Form 7 → New Feed
- Configure:
| Setting | Required | Notes |
|---|---|---|
| Feed Name | Yes | Label in the admin list |
| CF7 Form | Yes | Target form (must not rely on Signing tag for this mode) |
| WPsigner Template | Yes | Template with fields |
| Document Title | No | Supports {{signer_name}}, {{signer_email}}, {{date}}, {{company_name}}, … |
| Primary Signer → Name Field | Yes | CF7 tag name (e.g. your-name) |
| Primary Signer → Email Field | Yes | CF7 tag name (e.g. your-email) |
| Variable Mapping | No | custom.* → CF7 tag |
| Additional Signers | No | Extra name/email tag pairs |
| Auto-send document after creation | No | Default on in the UI |
| Feed enabled | No | Default on |
- Save Feed
Both primary Name and Email tag names are required for template feeds. If either is empty at submit time, that feed is skipped.
CF7 Tag Names
Section titled “CF7 Tag Names”[text* your-name] → your-name[email* your-email] → your-email[tel your-phone] → your-phone[textarea your-message] → your-messageThe tag name is the second token inside the brackets (after the field type).
Variable Mapping
Section titled “Variable Mapping”- Open Variable Mapping in the feed modal
- Add a row
- Left: variable name with
custom.*prefix (e.g.custom.company) - Right: CF7 tag name (e.g.
your-company) - Use
{{custom.company}}(or your template’s mapped field keys) in the PDF / prefill setup
| Variable | CF7 Tag | Example use |
|---|---|---|
custom.company | your-company | Company on contract |
custom.phone | your-phone | Phone line |
custom.amount | contract-amount | Pricing |
Variable names allow [a-zA-Z0-9_.] only.
Document Title Variables
Section titled “Document Title Variables”| Variable | Example |
|---|---|
{{signer_name}} | John Smith |
{{signer_email}} | john@example.com |
{{date}} | 2026-07-22 |
{{company_name}} | Acme Corp (when available) |
Example: NDA - {{signer_name}} - {{date}}
Additional Signers
Section titled “Additional Signers”Add rows with name field + email field tag names. With Auto-send enabled, each additional signer receives a signing request. Partial send progress is tracked so retries do not re-mail signers who already received the link.
Auto-send
Section titled “Auto-send”| Setting | Result |
|---|---|
| Enabled | Signing emails go out after the document is created; status moves toward Sent |
| Disabled | Document stays available in WPsigner → Documents for manual send |
Content-signing mode does not use this toggle (the form was already signed inline).
Integration Settings
Section titled “Integration Settings”WPsigner → Integrations → Contact Form 7
- Connection status and form / feed counts
- Feed list (name, Active/Disabled, form, mode: Inline signing vs template name, mapping count)
- New Feed, Edit, Enable/Disable, Delete
Admin AJAX uses nonce wps_cf7_nonce and requires manage_options (save capped at ~20 requests/minute per admin).
Document Owner
Section titled “Document Owner”There is no owner dropdown in the feed modal. Ownership resolves in this order:
- Feed
owner_user_id(set to the admin who saved the feed) - Option
wps_options['cf7_default_owner_id']if configured - Author of the page/post that contains the form (
_wpcf7_container_post) - Currently logged-in user
- First WordPress administrator
What Gets Created
Section titled “What Gets Created”Content signing outcome
Section titled “Content signing outcome”- Document status suitable for a completed embedded signature
- Signer marked signed
- Signature image stored as evidence
generate_completed→ completed PDF + Certificate of Completion- Document meta:
_wps_cf7_form_id,_wps_cf7_feed_id,_wps_cf7_content_signing - Audit events such as
document_sent,consent_accepted,otp_verified(when OTP used),embedded_signing_completed
Template feed outcome
Section titled “Template feed outcome”- Document from template + field prefills
- Audit
document_created - Optional auto-send → signing emails +
wps_document_sent - Signers complete the document on the WPsigner signing page (not inline)
Reliability & Limits
Section titled “Reliability & Limits”| Mechanism | Detail |
|---|---|
| Content rate limit | 10 content-signing operations / minute / form+IP |
| Template rate limit | 10 template documents / minute / form+IP |
| Dedupe (content) | Same form + browser binding + posted data → reuse result for ~5 minutes (no duplicate PDFs on double-submit) |
| Concurrency locks | Atomic locks prevent two parallel requests from creating two documents |
| Template send state | Durable state tracks sent_signer_ids for safe Auto-send retries |
| OTP one-time claim | Verified token can be reserved/consumed only once |
| Abort on failure | CF7 mail aborted; partial documents removed |
Developer Hooks
Section titled “Developer Hooks”/** * After a template-feed document is created. * * @param int $document_id * @param int $form_id CF7 form ID. * @param array $feed Sanitized feed config. * @param array $posted_data CF7 posted data. */do_action( 'wps_cf7_document_created', $document_id, $form_id, $feed, $posted_data );
/** * After inline content signing finishes (PDF + certificate ready). * * @param int $document_id * @param int $signer_id * @param array $posted_data * @param \WPCF7_ContactForm $contact_form * @param array $feed Configured or auto feed. */do_action( 'wps_cf7_content_signing_completed', $document_id, $signer_id, $posted_data, $contact_form, $feed);
/** * When template Auto-send finishes sending to signers. */do_action( 'wps_document_sent', $document_id, $signers );Security
Section titled “Security”| Feature | Details |
|---|---|
| Hook timing | Runs after CF7 validation; still before mail so merge tags work |
| Signature validation | PNG data-URI only; header / dimensions / GD checks; max payload size enforced |
| No base64 in email | Signing mail-tag replaced with Signed |
| Secure downloads | Completed PDF links use expiring public tokens |
| OTP session cookie | HttpOnly + SameSite=Strict; not IP-bound |
| Admin AJAX | wps_cf7_nonce + manage_options |
| Public OTP AJAX | wps_public_nonce + per-IP / per-email rate limits |
| Logs | Debug logs avoid raw PII (IDs / flags); phone hashes may be stored on the document |
Use Cases
Section titled “Use Cases”| Scenario | Mode | Setup |
|---|---|---|
| Website consent / waiver | Content signing | [insigner_signing* … otp:email] + merge tags in Mail |
| Support intake with signed acknowledgment | Content signing | Optional feed for CC to legal@ |
| NDA from contact form | Template feed | Template + Auto-send |
| Multi-party service agreement | Template feed | Additional signers + Auto-send |
| Quote → contract PDF | Template feed | Variable mapping for amount / company |
Multiple Feeds
Section titled “Multiple Feeds”- One form, multiple templates — all active template feeds for that form run (when no Signing tag is present)
- Multiple forms, one template — reuse the same PDF layout
- Inline + feed — Signing tag present → content signing only; template feeds on that form do not run
Troubleshooting
Section titled “Troubleshooting”Common Issues
Section titled “Common Issues”| Issue | Cause | Solution |
|---|---|---|
| Critical error on CF7 settings page | Outdated WPsigner without global \WPCF7_* class refs | Update to 3.0.3.2+ |
| No document / form shows error | Content signing aborted | Check signature PNG, OTP, debug log ([inSigner CF7]) |
| Template document not created | Feed disabled / wrong form / missing template | Verify feed Enabled, form ID, template |
| Template skipped silently | Missing name or email tag value | Confirm tag names and required fields |
| Merge tags empty | Tags used without successful content signing | Confirm Signing tag + successful submit; tags only resolve after PDF generation |
| OTP not sending | Channel or field misconfigured | Email field / Twilio / WhatsApp; check 429 rate limits |
| OTP verify fails after proxy | Old builds used IP fingerprint | Update plugin; ensure cookies allowed for the site |
| Duplicate documents | Rare race / old version | Update; dedupe + locks handle double-click / retries |
| Signer email never arrives (template) | Auto-send off or SMTP failure | Enable Auto-send; configure FluentSMTP / SMTP |
| Wrong signer mapped | Tag name mismatch | Names are case-sensitive (your-email ≠ Your-Email) |
| “Contact Form 7 is not installed” | CF7 inactive | Activate CF7 |
| Base64 spam in CF7 mail | Custom mail-tag misuse | Use merge tags above; do not print the raw signing field |
Debug Log
Section titled “Debug Log”define( 'WP_DEBUG', true );define( 'WP_DEBUG_LOG', true );Check wp-content/debug.log for [inSigner CF7] / [inSigner CF7 Content].
Quick Checklist
Section titled “Quick Checklist”- CF7 active; form published
- Content mode:
[insigner_signing*]present with valid Draw/Type/Upload value - OTP (if enabled): cookie not blocked; method available; email/phone mapped
- Template mode: no Signing tag; feed enabled; template + name/email tags
- Merge tags placed in Mail HTML body for content signing
- SMTP working if you expect CF7 or Auto-send emails
- Not hitting 10/min form rate limits while testing
Compatibility
Section titled “Compatibility”| Component | Supported |
|---|---|
| Contact Form 7 | 5.0+ (Tag Generator v2 / SWV tested on 5.9–6.x) |
| WPsigner | 3.0.3.2+ for full parity (inline signing, OTP, merge tags, before_send_mail) |
| WordPress | 5.8+ |
| PHP | 7.4+ |
CF7 vs Fluent Forms
Section titled “CF7 vs Fluent Forms”| Topic | Contact Form 7 | Fluent Forms |
|---|---|---|
| Field UI | Form-tag + tag generator | Native builder field |
| Processing hook | wpcf7_before_send_mail + $abort | Fluent validation / before-insert hooks |
| Merge tags | CF7 Mail + display message | Fluent email / confirmation parsers |
| Submission history | CF7 has no native entries; WPsigner document is the record | Fluent entry + meta |
| OTP AJAX | wps_cf7_send_otp / wps_cf7_verify_otp | wps_ff_* |
| Public hooks | wps_cf7_* | wps_fluentforms_* |
Shared: Draw/Type/Upload pad, PNG rules, OTP cookie model, Certificate of Completion, merge tag strings, optional feeds for CC/title/template mode.
Next Steps
Section titled “Next Steps”- Fluent Forms — Same workflows on Fluent Forms
- Smart Signing Forms — Standalone signing forms
- Twilio SMS — SMS OTP for CF7
- WhatsApp Business — WhatsApp OTP / notifications
- Creating Documents — Document statuses and actions
- REST API — Programmatic integrations
- Automation — n8n, Make, Zapier