> For the complete documentation index, see [llms.txt](https://kb.craftformswp.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://kb.craftformswp.com/documentation/form-building/embedding-forms-with-shortcodes.md).

# Embedding Forms With Shortcodes

CraftForms registers **two** shortcodes. Both render a form you have built in the CraftForms editor, but they serve different targets:

| Shortcode                  | Renders                                                                             | Use it for                                                                                                |
| -------------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| `[craftforms]`             | The form **inline**, server-side (`do_blocks()`)                                    | Any WordPress page/post/widget/page-builder that runs PHP                                                 |
| `[craftforms_static_form]` | A lightweight **embed placeholder** that fetches the live form over REST at runtime | Static-site exports / headless front ends (Astro, Hugo, [Builderius](https://builderius.io/) static site) |

***

### `[craftforms]` — inline render <a href="#craftforms--inline-render" id="craftforms--inline-render"></a>

Renders the selected form directly into the page and force-enqueues exactly the assets that form needs (Stripe, PayPal, file upload, booking datepicker, etc.). This is the universal embed path for page builders that can't drop in WordPress post content — paste it into Builderius' Shortcode module, a Bricks/Elementor shortcode/text element, a Gutenberg Shortcode block, or a widget.

#### Attributes <a href="#attributes" id="attributes"></a>

| Attribute      | Default | Required | Description                                                                                                                                                                            |
| -------------- | ------- | :------: | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `form`         | —       |     ✅    | Form **post ID**. Nothing renders if missing/empty.                                                                                                                                    |
| `catalog-item` | `0`     |          | Catalog **resource ID** (PRO). Scopes the form's field options, pricing formula, smart-variable overrides and booking availability to that catalog resource. Ignored on the free plan. |
| `product`      | `0`     |          | WooCommerce **product ID** (PRO + WooCommerce). Renders the form as that product's add-to-cart form on **any** page — see below.                                                       |

#### Examples <a href="#examples" id="examples"></a>

```
[craftforms form="42"]
[craftforms form="42" catalog-item="7"]
[craftforms form="42" product="99"]
```

#### `product` — add to cart from anywhere <a href="#product--add-to-cart-from-anywhere" id="product--add-to-cart-from-anywhere"></a>

On a WooCommerce single-product page, a connected CraftForms form automatically replaces the default add-to-cart form. The `product` attribute lets you place that **same add-to-cart form on any other page** (landing page, custom builder layout, a different post). Submitting it adds the product to the cart with the form's computed price, custom fields, dynamic SKU, weight/dimensions and generated preview — identical to the product page.

Requirements — the product must be:

1. a **simple** product,
2. **connected to the same form** (on its product-data tab) you pass in `form`.

If the pair doesn't satisfy these, **the form still renders** **without** add-to-cart functionality (which means the the form submission will not lead to adding the product to cart; so a contact/quote form degrades gracefully), and logged-in editors see an HTML comment explaining why. A forged or mismatched `product` id can never add an unrelated product — the server re-validates the form↔product connection on submit.

`catalog-item` and `product` are independent paths; when `product` resolves to a valid connected form it takes over the render, so combining both is not needed.

***

### `[craftforms_static_form]` — headless / static-site embed (PRO) <a href="#craftforms_static_form--headless--static-site-embed-pro" id="craftforms_static_form--headless--static-site-embed-pro"></a>

Instead of baking the form HTML (with a soon-stale nonce and a `/wp-json/` URL) into the page, this emits a placeholder `<div data-craftforms-embed="KEY">` plus a one-time `embed.js` loader. On the visitor's browser, `embed.js` fetches the current form markup, pricing logic and (for booking) availability from your WordPress backend over REST. The output is therefore safe to **freeze into a static export** and keeps working against a [locked-down backend](/documentation/for-developers/headless-backend-mode.md).

Returns nothing on the free plan.

#### Attributes <a href="#attributes-1" id="attributes-1"></a>

| Attribute      | Default | Description                                                                                                                |
| -------------- | ------- | -------------------------------------------------------------------------------------------------------------------------- |
| `key`          | `''`    | Embed key from **Settings → Embed**. Takes precedence over `form`.                                                         |
| `form`         | `''`    | Form reference — post **ID, UUID, or REST name**. When `key` is empty, its registered embed key is resolved automatically. |
| `resource-id`  | `''`    | Catalog **resource ID** for catalog pricing / booking availability.                                                        |
| `catalog-item` | `''`    | Alias of `resource-id` (used only when `resource-id` is empty).                                                            |

If no embed key can be resolved, logged-in editors get a guidance comment and the public page renders nothing.

#### Examples <a href="#examples-1" id="examples-1"></a>

```
[craftforms_static_form form="42"]
[craftforms_static_form key="a1b2c3…"]
[craftforms_static_form form="42" catalog-item="7"]
```

#### Catalog & booking over the embed <a href="#catalog--booking-over-the-embed" id="catalog--booking-over-the-embed"></a>

When `resource-id` / `catalog-item` is supplied, the backend **re-renders the form live with that resource applied** before returning it, so the static embed behaves the same as the inline shortcode:

* **Catalog pricing/options:** the catalog price formula, merged option values and smart-variable overrides are baked into the returned HTML — what the shopper sees matches what they're charged on submit.
* **Booking:** the datepicker receives its resource binding, booking window, schedule and availability/slots endpoints, so remaining-capacity checks work.

Availability is refreshed on discrete events — datepicker init, relevant field changes, this form's own successful submit, and once more right before Stripe/PayPal payment — plus an authoritative capacity re-check server-side on submit. There is **no** live cross-user polling; a slot another visitor just took becomes visible on the next of those events (or a reload).

#### Hardened backends <a href="#hardened-backends" id="hardened-backends"></a>

All CraftForms REST URLs baked into the embed — form submission **and** the booking datepicker's availability/slots endpoints — are emitted in `?rest_route=` form, so the embed works even when `/wp-json/` is blocked at the server level.

#### WooCommerce note <a href="#woocommerce-note" id="woocommerce-note"></a>

There is intentionally **no** `product` (add-to-cart) support in the static embed — a static site has no WooCommerce cart. Use `[craftforms product="…"]` (inline) on a WordPress page for add-to-cart.

***

### Readiness at a glance <a href="#readiness-at-a-glance" id="readiness-at-a-glance"></a>

| Form type                            | `[craftforms]` (inline) | `[craftforms_static_form]` (embed) |
| ------------------------------------ | :---------------------: | :--------------------------------: |
| Simple contact                       |            ✅            |                  ✅                 |
| Product form, self-contained pricing |            ✅            |                  ✅                 |
| Catalog-connected pricing/options    |            ✅            |                  ✅                 |
| Booking (catalog resource)           |            ✅            |                  ✅                 |
| WooCommerce add-to-cart (`product`)  |       ✅ (any page)      |     — (no cart on static sites)    |

***

### Page builders <a href="#page-builders" id="page-builders"></a>

* **Builderius / Bricks / Elementor / Gutenberg /** **Etch:** drop `[craftforms form="…"]` into a shortcode/text module.
* **Bricks** and **Elementor** additionally ship a native **"CraftForms Form"** element/ widget (form selector + catalog-item control) — use it instead of the shortcode there if you prefer a visual control. Builderius uses the shortcode.
