> ## Documentation Index
> Fetch the complete documentation index at: https://docs.hiveku.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webflow Automations

> Start a Hiveku workflow from a Webflow event and drive the site back through 110 Webflow action nodes, with a worked recipe that turns a published CMS item into a social draft and a Slack message.

A connected Webflow site is a first-class source of workflow triggers and a first-class target for workflow actions. Thirteen trigger nodes listen to what happens on the site; 110 action nodes cover every operation in Hiveku's Webflow registry, one node per operation.

If you are new to the workflow editor, read [Workflows](/integrations/workflows) and the [Workflow Node Reference](/integrations/workflow-nodes) first. This page is only what is different about Webflow.

## Triggers need webhooks registered first

Webflow triggers fire from webhooks Webflow sends to Hiveku. Hiveku registers eleven of them per site when you connect, and nothing fires until they exist.

<Warning>
  Two connections start with no webhooks: one made by pasting a **site API token** (Webflow refuses webhook registration for site tokens, so the connect answers `site_token_refused` and leaves you a manual instruction), and any connection made before Hiveku registered webhooks at connect time.
</Warning>

The fix is the same in both cases: re-register from the connection. The Webhooks panel in the [Webflow workspace](/integrations/webflow/workspace) has the button, and it posts to `POST /api/builder/webflow/connections/[id]/reregister-webhooks`. See [Connecting Webflow](/integrations/webflow/connecting) for the connection kinds and what each one can do.

<Note>
  Re-registering is **admin or owner only**, the same gate as disconnecting, because a registration affects every project on the connection. A site-token connection answers `412 oauth_required` — reconnect that site with OAuth first. Per site, the new registrations are created before the old ones are deleted, so a failure part-way leaves duplicates (which the receiver deduplicates by event id) rather than a gap.
</Note>

## The trigger nodes

Every workflow starts with exactly one trigger. Search the palette for `Webflow:` to find these.

| Palette label                      | Fires on                                                                                                   | Beyond the common keys, it carries                                                                            |
| ---------------------------------- | ---------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |
| **Webflow: Site Published**        | The site being published                                                                                   | `published_on`                                                                                                |
| **Webflow: CMS Item (any event)**  | Every `collection_item_*` event; narrow with the event-type filter                                         | `item_id`, `collection_id`, `slug`, `is_draft`, `is_archived`, `last_updated`, `last_published`, `field_data` |
| **Webflow: CMS Item Created**      | An item created, staged and not yet live                                                                   | The same CMS item keys                                                                                        |
| **Webflow: CMS Item Changed**      | A staged item changing                                                                                     | The same CMS item keys                                                                                        |
| **Webflow: CMS Item Deleted**      | An item deleted. The payload is id-only: `slug` and `field_data` are null                                  | `item_id`, `collection_id`                                                                                    |
| **Webflow: CMS Item Published**    | An item going live. The anchor for "new post, do something"                                                | The same CMS item keys                                                                                        |
| **Webflow: CMS Item Unpublished**  | An item taken off the live site                                                                            | The same CMS item keys                                                                                        |
| **Webflow: Page Created**          | A page created. The page index is synced before the fire                                                   | `page_id`, `page_title`, `last_updated`                                                                       |
| **Webflow: Page Deleted**          | A page deleted                                                                                             | `page_id`, `page_title`, `last_updated`                                                                       |
| **Webflow: Page Metadata Updated** | A page's title, slug, SEO or Open Graph changing                                                           | `page_id`, `page_title`, `last_updated`                                                                       |
| **Webflow: Comment Created**       | A Designer comment thread or reply. An inbox item is seeded first                                          | `thread_id`, `page_title`, `content`                                                                          |
| **Webflow: Form Submission**       | A form on the site being submitted                                                                         | See below — a different shape                                                                                 |
| **Webflow: Any Event**             | Catch-all for every non-form Webflow event, the ecommerce ones included. Never fires for a form submission | The raw `payload` only, with no per-family flattening                                                         |

### What every non-form trigger carries

`trigger_type`, `event_id`, `site_id`, `connection_id`, `verification`, `project_ids`, `project_id`, `payload`, `received_at` and `timestamp`, plus that family's flattened keys.

Two of those are worth knowing:

* **`payload`** is Webflow's own delivery, untouched. When a flattened key is null (a deleted item, say) the raw payload is still there.
* **`verification`** is `hmac` for an OAuth connection whose delivery signature Hiveku checked, or `url_token` for a site-token connection, where the secret in the receiver URL is the whole check. Branch on it if a workflow does something you would only do on a signed delivery.

`project_id` is the first bound project and `project_ids` is every binding — one Webflow site can fan out to several Hiveku projects.

### The form submission trigger is not a second event

**Webflow: Form Submission** is the ordinary Form Submitted trigger narrowed to Webflow, fired through the Hiveku Forms ledger rather than straight off the webhook. That means it inherits the ledger's spam, duplicate and freshness guards, its contact resolution and its attachment handling — and it carries the ledger's shape, not the Webflow event shape:

`formId`, `projectId`, `submissionId`, `data`, `contactId`, `utm`, `attachments`, `source`, `site_id`, `webflow_submission_id`, `webflow_event_id`, `form_name`, `timestamp`.

<Note>
  A workflow holding both the Webflow form trigger and the generic Form Submitted trigger still runs **once**. It is one event reaching the engine through one path, not two.
</Note>

### Narrowing the two catch-alls

**Webflow: CMS Item (any event)** takes an event-type filter, so one node can cover created plus published without three copies of the same branch. **Webflow: Any Event** takes a trigger-type filter and is how you reach the events Hiveku has no dedicated node for, including `ecomm_new_order`, `ecomm_order_changed` and `ecomm_inventory_changed`. Branch on `{{trigger.trigger_type}}` inside it.

The filters compose with AND, and every node takes them:

| Filter        | Available on                                      |
| ------------- | ------------------------------------------------- |
| Site, project | Every Webflow trigger                             |
| Collection    | Every CMS item trigger, the umbrella one included |
| Event types   | **Webflow: CMS Item (any event)**                 |
| Page          | The three page triggers                           |
| Trigger types | **Webflow: Any Event**                            |

<Note>
  A filter value the engine cannot use fails **closed**. A collection filter pointing at a collection that no longer exists stops the workflow firing; it never widens back to "any collection".
</Note>

### A workflow's own writes do not re-trigger it

A Webflow write made by a workflow node makes Webflow deliver the matching webhook straight back. Without a guard, "on item changed, update the item" would loop forever.

Hiveku notes the Webflow object id after every successful workflow write and skips the workflow that wrote it for **three minutes**. The scope is deliberate: the guard is keyed by account, object id and workflow id, so a *different* workflow listening to the same item still fires.

## The action nodes

There are **110** Webflow action nodes, one per registry operation. Sixteen are hand-written and get the richer configuration panel; the other 94 are generated from the operation schemas, and a sync test fails the build if the two lists ever drift from the registry.

### The sixteen featured nodes

| Node                          | What it does                                                                                                                                                  |
| ----------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Webflow: CMS Item Create      | One staged item from a JSON `field_data` object, **created as a draft unless you set `is_draft` false**. Live only after CMS Item Publish, which skips drafts |
| Webflow: CMS Item Update      | The staged copy of one item; only the keys you pass change                                                                                                    |
| Webflow: CMS Item Publish     | Up to 100 items live, **skipping any still marked draft**. Items go live **without** a site publish                                                           |
| Webflow: CMS Item Unpublish   | Removes the live copy; the staged item is kept                                                                                                                |
| Webflow: CMS Item Delete      | Permanent, live copy included. Confirm must be ticked                                                                                                         |
| Webflow: Page Metadata Update | Title, slug, SEO, Open Graph. Staged until a site publish                                                                                                     |
| Webflow: Page Schema Set      | Sets or clears a page's JSON-LD. Staged until a site publish                                                                                                  |
| Webflow: Site Publish         | Every custom domain, a subset, or one page. Confirm must be ticked; one publish per minute per site                                                           |
| Webflow: Asset Upload         | A file from a public URL or the Media Library, returning its hosted CDN URL                                                                                   |
| Webflow: Snippet Install      | The Hiveku analytics or annotation snippet. OAuth connections only; takes effect after a site publish                                                         |
| Webflow: llms.txt Set         | The site's llms.txt for AI crawlers. Enterprise sites only                                                                                                    |
| Webflow: CMS Collection List  | Discover collection ids at run time. Read-only                                                                                                                |
| Webflow: CMS Item Query       | Search one collection by name or slug over staged or live copies. Read-only                                                                                   |
| Webflow: CMS Item Get         | One item with its full `fieldData`, typically `{{trigger.item_id}}`. Read-only                                                                                |
| Webflow: Page List            | Every page with id, slug, title, SEO and Open Graph. Read-only                                                                                                |
| Webflow: Form Submission Get  | One submission by Webflow's id, typically `{{trigger.webflow_submission_id}}`. Read-only                                                                      |

### The 94 generated nodes, by family

The palette groups them exactly like this:

| Family                          | Nodes | Family      | Nodes |
| ------------------------------- | ----- | ----------- | ----- |
| Ecommerce                       | 15    | Redirects   | 4     |
| Custom Code                     | 8     | Robots      | 4     |
| Assets                          | 6     | Site        | 3     |
| CMS Items                       | 6     | Google Tag  | 3     |
| Schema (collections and fields) | 6     | llms.txt    | 2     |
| Comments                        | 5     | Well-Known  | 2     |
| Components                      | 5     | Token       | 2     |
| Forms                           | 5     | Collections | 1     |
| Page Content                    | 5     | Pages       | 1     |
| Page SEO                        | 5     | Activity    | 1     |
| Webhooks                        | 5     |             |       |

Each generated node is registered under a camelCase type and a `webflow_<action>` snake\_case alias. The snake spelling is also the name of the matching MCP tool and takes the same argument keys, so a flow you prototyped in a chat transfers to the canvas without renaming anything.

### What the nodes inherit from the registry

Workflow nodes are thin envelopes over the same operation runner the AI chat and the dashboard panels use, reached over the Olympus route. They inherit its behaviour rather than reimplementing it:

<AccordionGroup>
  <Accordion title="Confirm-gated nodes have a checkbox" icon="check">
    Nineteen operations are confirm-gated — the deletes, order fulfil and refund, replacing robots.txt, updating a webhook, and the site publish. Seventeen of them are generated nodes and two are featured. The node refuses to run unless the confirm box is ticked, and the panel shows the operation's own sentence about what it is about to do.
  </Accordion>

  <Accordion title="Staged writes report publish_required" icon="clock">
    A write that lands on the staged site rather than the live one is flagged `staged` on its spec, and the node's output carries `publish_required: true`. Chain a **Webflow: Site Publish** at the end of the branch, or leave it staged on purpose and let a person publish.
  </Accordion>

  <Accordion title="Dry runs return a mock, never a write" icon="flask">
    In a dry run a write node returns a `would_have` payload built from the arguments it resolved, plus `publish_required: true` when the operation stages. Nothing reaches Webflow. Dry-run every Webflow branch before you enable it.
  </Accordion>

  <Accordion title="OAuth, Enterprise and locale gates still apply" icon="lock">
    Fifteen operations refuse a site-token connection with `412 oauth_required` (the nine custom-code ones, the three page custom-code ones, webhook create, webhook update, and reading the authorizing user). Fourteen need a Webflow Enterprise workspace and answer `402` otherwise (redirects, robots.txt, llms.txt, well-known files, the activity log). Three need a secondary locale id and answer `412 secondary_locale_required` without one: page DOM update, component content update, component properties update.
  </Accordion>

  <Accordion title="Retries do not double-write" icon="rotate">
    Every write node sends an `Idempotency-Key` derived from the step and the run, so a retry after a timeout replays the stored response instead of creating the item twice. Publishes are the deliberate exception: the route ignores the key for `site_publish`, `cms_item_publish` and `cms_item_unpublish`, because a repeat publish is the point.
  </Accordion>
</AccordionGroup>

## Recipe: a published item becomes a social draft and a Slack ping

The shape below is the most common Webflow automation: someone publishes a blog post in Webflow, and the team gets a drafted social post and a message in the channel.

<CardGroup cols={4}>
  <Card title="1. Trigger" icon="bolt">
    Webflow: CMS Item Published
  </Card>

  <Card title="2. Read" icon="book-open">
    Webflow: CMS Item Get
  </Card>

  <Card title="3. Write" icon="wand-magic-sparkles">
    AI Agent, then Create Social Post
  </Card>

  <Card title="4. Tell" icon="slack">
    Slack Notification
  </Card>
</CardGroup>

<Steps>
  <Step title="Add the trigger">
    **Add Trigger**, search `Webflow:`, pick **Webflow: CMS Item Published**. Set the collection filter to your Blog collection so a published case study does not fire it. The collection, page, site and project choices in these nodes are served from the connected site, so you pick from a list rather than paste an id.
  </Step>

  <Step title="Read the full item">
    Add **Webflow: CMS Item Get**. Set `collection_id` to `{{trigger.collection_id}}` and `item_id` to `{{trigger.item_id}}`.

    Do this even though the trigger carries `field_data`: the trigger payload is what Webflow delivered, and reading the item back gives you the whole record with the field slugs the collection actually defines.
  </Step>

  <Step title="Draft the copy with an AI Agent">
    Add an **AI Agent** node and write a prompt that names the fields you want it to use:

    ```
    Write one LinkedIn post about this new article, in our brand voice,
    under 900 characters, no hashtags, ending with the link.

    Link: https://example.com/blog/{{trigger.slug}}
    ```

    For the title, the summary and anything else the collection holds, type `{{` in the prompt box and pick them out of the CMS Item Get step's output in the autocomplete rather than guessing a path — the field names are your collection's own slugs. Point the node at the department whose voice you want, and turn on the knowledge base if the post should quote positioning the agent would not otherwise know.
  </Step>

  <Step title="Create the social post as a draft">
    Add **Create Social Post**. Set `content` to the AI Agent's output, pick the platforms, and leave `status` as the default draft so a person approves before anything is published. Nothing on a social account changes until that approval.
  </Step>

  <Step title="Tell the channel">
    Add **Slack Notification** with your channel and webhook URL, and a message that links both ends:

    ```
    New post live on the site: {{trigger.slug}}
    A social draft is waiting for approval.
    ```
  </Step>

  <Step title="Dry-run, then enable">
    Run it as a dry run first. The Webflow read returns real data; the social node reports what it would have created. Then enable it and publish one real item to watch it end to end.
  </Step>
</Steps>

<Tip>
  Publishing an item in Webflow is what fires this. Saving an item stages it and fires **CMS Item Changed** instead — useful if you want a review step before anything goes live, and the reason the published trigger exists as its own node.
</Tip>

### Variations worth knowing

| Instead of                              | Use                                                                                                              |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| Reacting to one collection              | **Webflow: CMS Item (any event)** with an event-type filter, then branch on `{{trigger.trigger_type}}`           |
| Reacting to a publish of the whole site | **Webflow: Site Published**, which carries `published_on`                                                        |
| Reacting to a Webflow form              | **Webflow: Form Submission** — it already carries the resolved `contactId`, so the CRM step is often unnecessary |
| Reacting to an order on a Webflow store | **Webflow: Any Event** filtered to `ecomm_new_order`                                                             |
| Writing back to the site                | Any of the 110 action nodes, remembering that a staged write needs **Webflow: Site Publish** to reach visitors   |

## What's next

<CardGroup cols={2}>
  <Card title="Workflows" icon="diagram-project" href="/integrations/workflows">
    Triggers, conditions, actions and merge variables, in general.
  </Card>

  <Card title="Workflow node reference" icon="list" href="/integrations/workflow-nodes">
    Every node category in the editor, Webflow included.
  </Card>

  <Card title="The Webflow AI chat" icon="comments" href="/integrations/webflow/ai-chat">
    The same operations, asked for in plain words rather than wired on a canvas.
  </Card>

  <Card title="Webflow for developers" icon="code" href="/integrations/webflow/developers">
    The inbound receiver, the reliability crons, and the error codes the nodes surface.
  </Card>
</CardGroup>
