Skip to content

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 enabled
  • ad_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:

  1. Checks publish/schedule/login
  2. Verifies the per-form nonce
  3. Silently succeeds (no store) when the honeypot is filled
  4. Sanitizes all input fields, evaluates visibility, then validates visible fields only
  5. Stores ad_form_submissions + ad_form_submission_meta and increments submission_count
  6. 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.

Digitale Lösungen. Persönlich. Zukunftssicher.