Hooks.
A plugin runs when a hook fires. You declare which hooks a plugin listens on, and export a handler for each. Four hooks are wired into the request and lead pipeline today; the rest are reserved for future use.
A handler receives a single input object and returns a value the pipeline uses. Inputs are stripped to plain, serialisable data before they reach your code, and sensitive fields (cookies, authorization headers, a user's password and settings) are removed. If a handler throws or times out, the pipeline logs it and continues with the value unchanged, so a plugin can never take a page down.
The wired hooks
| Hook | Fires | Input | Return |
|---|---|---|---|
pre_request |
Before the request is handled. | { site, path, method, headers, query } |
Optional { headers, status, body }. A numeric status short-circuits the request. |
pre_render |
Before the Liquid render. | { site, page, template, requestPath, context } |
A partial map, merged into the render context. |
post_render |
After the render. | { site, page, html, requestPath } |
New html (a string, or { html }). |
lead_received |
When a lead is captured. | { lead, site } |
Ignored. Fire and forget. |
Adding to the render context
The most common use is pre_render: compute something and hand it to the template. Whatever the handler returns is merged into the context, so the template can read it.
module.exports = {
pre_render: (input) => {
const featured = input.page && input.page.tags.includes('featured')
return { is_featured: featured }
}
}The template then reads {{ is_featured }}. To transform the finished page instead, use post_render and return a new html string.
Ordering
pre_requestplugins run in declaration order; the first to return astatusends the request.post_renderplugins run in sequence, each seeing the previous plugin'shtml.pre_renderresults are merged together into one context.lead_receivedplugins run in parallel and their results are not used.
Reserved hooks
The full set of hook names also includes liquid_filter, liquid_tag and webhook, which are declared but not yet dispatched, and scheduled, which is driven by the scheduling system rather than a request. Treat the four wired hooks above as the supported surface today. The runtime manifest reports, in its hooks list, exactly which are wired, so build against that rather than a fixed assumption.