Darstellung
Frontend renderer
Phase 4 renders published forms on the public site and accepts submissions.
Shortcode
[ad_form id="1"]
[ad_form slug="contact"]Only published forms are shown to visitors. Editors with edit_ad_form_forms see a preview of drafts, disabled and scheduled forms.
Scheduling uses starts_at / ends_at. require_login replaces the form with a notice for logged-out visitors.
Markup
The renderer walks definition.fields and asks each registered field type for HTML. Unknown types fall back to a text input. If the definition has no submit field, a submit button is appended.
When definition.steps has two or more entries, fields are grouped into .ad-form__step pages with progress and Back/Next controls. Inactive pages are hidden only after JavaScript runs; inputs stay enabled so a no-JS POST still includes every field. See STEPS.md.
Hidden controls:
ad_form_nonce– per-form nonce (ad_form_submit_{id})ad_form_hp– honeypot when enabledad_form_values[key]– submitted values
CSS/JS load only after a form is marked present (Frontend\Assets). The main query is scanned on wp_enqueue_scripts for [ad_form], <!-- wp:ad-form/form and Elementor _elementor_data (widgetType: ad-form) so styles can print in wp_head. Widgets and page builders still enqueue during shortcode/block/widget render; late styles print in wp_footer.
Submit
Classic POST posts to the current page (template_redirect). When settings.ajax is true (default), assets/frontend/js/form.js sends POST /wp-json/ad-form/v1/forms/{id}/submit.
AJAX body:
json
{
"nonce": "...",
"honeypot": "",
"source": "shortcode",
"values": {
"email": "ada@example.com"
}
}nonce is the per-form action ad_form_submit_{id}. Logged-in visitors also send WordPress cookie auth as X-WP-Nonce (wp_rest), taken from data-wp-rest-nonce.
The handler:
- Checks publish/schedule/login
- Verifies the per-form nonce
- Silently succeeds (no store) when the honeypot is filled
- Sanitizes all input fields, evaluates visibility, then validates visible fields only
- Stores
ad_form_submissions+ad_form_submission_metaand incrementssubmission_count - Runs enabled submit actions whose conditions match (email notifications). Mail failures are logged and do not fail the request.
Hidden fields are omitted from the payload and meta. Required rules do not apply while a field is hidden.
Confirmation: inline message or wp_safe_redirect to redirect_url.
IP storage follows plugin settings (none / hashed HMAC / anonymized then hashed). The column is always a hash, never a raw address.
Conditional logic
Enabled field groups are serialized as data-conditions. form.js shows or hides wraps with is-conditionally-hidden, disables controls, and toggles required from data-required. AJAX submit skips hidden values. Classic POST applies conditions first so disabled inputs are dropped. See CONDITIONS.md.
Calculations
Number fields use type="number". Calculation fields are read-only inputs with data-formula. form.js updates them on input/change using the same parser as PHP. Submit always recalculates on the server. See CALCULATIONS.md.
Gutenberg
The block ad-form/form renders through the shortcode with source=gutenberg. The editor shows a picker, not a live form. See GUTENBERG.md.
Elementor
The widget ad-form renders through the shortcode with source=elementor. The editor shows a SELECT of published forms and a placeholder canvas, not a live form. See ELEMENTOR.md.
Next
Phase 12 adds form templates.