--- name: clickfunnels-sdk-external-page description: > Add the ClickFunnels SDK to a page you host yourself - your own domain, a static host, a Netlify/Vercel site, or even a local file:// - so it tracks visits, captures opt-ins, and carries contact identity across funnel steps. Use this skill when embedding the SDK into an HTML page: the cf-page-token meta tag, the sdk.js script, and the data-cf-element form markup the SDK reads. The page is registered with ClickFunnels - as a funnel step, or standalone (registered for tracking now, placed in a funnel later). version: "1.0" author: ClickFunnels references: - path: https://accounts.myclickfunnels.com/llms.txt description: Product overview + skills index. - path: https://accounts.myclickfunnels.com/.well-known/funnels/skill.md description: Build/modify the funnel that hosts this page (incl. placing standalone external pages in split branches). - path: https://accounts.myclickfunnels.com/.well-known/pages/skill.md description: Author CF-hosted pages programmatically (companion to externally-hosted SDK pages). - path: https://accounts.myclickfunnels.com/.well-known/sdk/add-checkout/skill.md description: Sell products from an external page - checkout, order bumps, one-click one-time offers. --- # ClickFunnels SDK - Create an External Page An **external page** is a page you host anywhere on the web that behaves like a native ClickFunnels funnel step: visitors are tracked, forms submit into CF (contact creation, opt-in events, automations), and contact + visit identity carries across steps - even when steps live on different domains. You wire this up with **three tags and one attribute**. That is the entire public surface. Everything else is internal to the SDK and handled for you. ## When to use this skill - You have an HTML page (own domain, static host, Netlify/Vercel, or localhost for local development, possibly also `file://` with certain limitations, like form submission not working) and want it to act as a ClickFunnels opt-in / capture step. - You're fixing a page where the SDK "isn't doing anything" - usually a missing `data-cf-element`, a stray form-level marker, or `sdk.js` pointing at the wrong host. - You're adding a new field to an SDK-driven form. ## Register the page in ClickFunnels first The SDK only works on a registered page: registration mints the page token. The page can be placed into a funnel at registration time, or registered **standalone** (no funnel step yet) and placed later. Two ways to do it: - **Funnel builder (UI).** Open your funnel, add a step, and pick **External page**. Enter the page's public URL and a name. ClickFunnels then shows the exact two snippets to paste - the token meta tag and the script tag for **your** account's SDK host. - **API.** `POST /api/v2/workspaces/:workspace_id/pages/external` returns the same token and URL in an `sdk` block - see [Create the external page via the API](#create-the-external-page-via-the-api). ## The entire public surface ### 1. Page token - `` Paste the `cfp_...` token ClickFunnels issued for this page into a meta tag in `
`: ```html ``` The token (format `cfp_` + 24 alphanumeric characters) is how the SDK identifies the page - not the URL. **One token per page**; never paste the same token onto two different pages. For a single-page app that swaps routes without a full navigation, update the `content` attribute when the active "page" changes - the SDK observes the meta tag and re-initializes against the new token. ### 2. The SDK script Load the SDK once per page. Anywhere on the page works (it discovers and enhances forms continuously, including ones added later): ```html ``` `defer` lets the page finish parsing before the SDK runs, which avoids race conditions no matter where the tag sits. In a single-page app, load it **once** for the whole app - the SDK keeps watching for forms (and for `cf-page-token` changes) across client-side route changes, so you don't re-add it per route. ### 3. Mark elements with `data-cf-element` A single attribute identifies every SDK-aware element. Its value names what the element is: ```html ``` - Values are **flat, kebab-case** identifiers (`email`, `first-name`, `phone`). No flow prefixes - a field is a field regardless of which funnel it's in. - Keep your own `name`/`id` attributes for labels, styling, and accessibility. The SDK reads **identity** from `data-cf-element`, not from `name`/`id`, and builds the submission payload itself. - There is **no** form-level marker. The SDK finds the form by walking up from the `data-cf-element` elements inside it. #### Custom contact attributes - `custom-attribute: