Forms Auto Submit
Submit exact pre-filled form answers from a short-lived, server-signed link.
Forms Auto Submit adds a second, intentionally narrow way into Forms: opening a signed link submits the exact answers embedded in that link. It is useful for one-click actions such as Yes, I'll attend or Confirm my booking. The accepted entry and its background deliveries use the normal Forms pipeline.
This feature requires a server-side integration
The form editor does not generate a generic mail-merge URL. A template such as
?email=[EMAIL] cannot be signed safely because changing the placeholder after
signing would also change the authorized submission. Your application or mailing
system must resolve every answer first, then ask WordPress to build one concrete
signed URL for that recipient.
Turn it on
Edit the form, open the Auto Submit panel in the document sidebar and switch Enable on.
Update the form. A copied form starts with Auto Submit disabled.
Have a server-side integration call
XPACGroup\Plugin\FormsAutoSubmit\Addon::buildSignedUrl() after it knows the
exact values for one recipient. Send the returned URL unchanged.
For example:
use XPACGroup\Plugin\FormsAutoSubmit\Addon;
$url = Addon::buildSignedUrl(
128,
[
'email' => 'jane@example.com',
'rsvp' => 'yes',
],
30 * MINUTE_IN_SECONDS
);
if (is_wp_error($url)) {
// Do not send a link; log or handle $url->get_error_code().
}The third argument is an optional lifetime in seconds. When omitted, links last one
hour. Lifetimes are clamped to a minimum of five minutes and a maximum of seven days.
The xpac_forms_autosubmit_link_ttl filter can change the default inside the same
bounds.
buildSignedUrl() returns string|WP_Error. It refuses an unavailable form, unknown
field names, nested or associative values, File Upload, Consent and Password values,
and URLs longer than 8,192 bytes. Values may be strings/scalars or flat indexed lists
for multi-value fields. The builder percent-encodes them; do not edit or append query
arguments afterwards.
What the link contains
A pretty-permalink link resembles:
https://example.com/submit_form/128/?email=jane%40example.com&rsvp=yes&xpac_as_id=…&xpac_as_exp=…&xpac_as=…Plain-permalink sites use /?xpac_forms_action=autosubmit&form_id=128 instead. The
xpac_as_exp argument is the required Unix expiry, xpac_as_id is a random
20-character request instance, and xpac_as is an HMAC covering the form id, instance,
expiry and canonical exact answer values. Altering, adding, removing or reordering a
multi-value answer invalidates the link. Duplicate keys, scalar/array ambiguity and
nested query values fail closed before PHP's query parser can hide them.
Answers are still visible in the URL. They can appear in email-security reports, browser history, proxy/CDN and server logs, analytics and referrer data. Prefer opaque identifiers and never put passwords, secrets, consent or file contents in a link.
What happens when it opens
The route accepts only GET, a published and accessible form, an exact valid signature
and a non-expired bounded expiry. Forms' per-IP/per-form throttle then runs. Normal
validation, entry storage, idempotency and background delivery queuing follow. The
instance marker, safe retry payload and named delivery manifest are committed atomically
with the entry. Replaying the same URL reports that it was already received and resumes an
interrupted named-delivery discovery/scheduling phase without creating another entry or
duplicate job. A completed irreversible-mutation recovery also skips the link's throttle
and pre-submit extension hook because those phases already accepted. Google reCAPTCHA and
Cloudflare Turnstile cannot run on this link-only path;
Akismet and the honeypot still run.
On a validation failure the visitor sees a short summary. A disabled link returns HTTP 410 with a clear unavailable message and creates no entry or delivery. A configured safe redirect is followed; an empty redirect is not converted into a silent trip to the home URL.
Opening the link is the write
The link is single-effect, not proof that its intended recipient opened it. A mail scanner, chat preview or browser prefetcher can consume it first; the recipient then sees “already received.” Do not use Auto Submit for payments, stock, scarce reservations or another action where the identity or intent of the first opener matters.
File, Consent and write-only fields are not supported
File, Consent, Password and Confirmation fields are refused even when optional. A legacy text field mapped to a UserAuth password is refused as well. A required one therefore makes the form unsuitable for Auto Submit. Use the ordinary form when the visitor must upload, actively consent or enter or repeat a secret.
Lower-level signing API
An integration that must assemble the URL itself can call:
$signature = Addon::signLink($formId, $exactValues, $expiry, $instanceId);It returns string|WP_Error and applies the same form, value, instance and expiry
checks. $instanceId must be a newly generated 20-character lowercase alphanumeric
value and the URL must carry it unchanged in xpac_as_id, alongside the exact values,
positive expiry in xpac_as_exp, and signature in xpac_as. buildSignedUrl() is safer
because it generates the instance and cannot accidentally encode a different value
shape.
Historical signatures covering only form_id|expiry and never-expiring placeholder
links are rejected by default. A site may temporarily opt into that unsafe migration
path with xpac_forms_autosubmit_allow_legacy_form_signature, but doing so makes every
answer mutable again, permits expiry zero and lacks the signed instance that guarantees
one effect. Reissue concrete links instead. The old
xpac_forms_autosubmit_require_signature bypass is no longer honored.
Settings remain in Forms' form_settings post meta under
{ autosubmit: { enable: boolean } }. xpac_forms_autosubmit_unsafe_fields can add to
the refused field-name list, and xpac_forms_autosubmit_pre_submit fires after all
route gates and before Submission::submit(). The shared
xpac_forms_submit_response filter receives the same normalized response keys as the
REST submit route; malformed or throwing callbacks cannot turn a durably stored entry
into a visible failure.
Conditional Logic
Show, hide, or disable form sections and gate delivery actions with conditions evaluated in the browser and again on the server.
Submission To Post
Turn each form submission into a WordPress post, with the answers filling the title, content, excerpt, featured image, taxonomy terms and custom fields.