URL: /choose-your-path # Choose Your Path Same product, three different first weeks. Pick your job below. Goal: more of the traffic you already have turning into pipeline, and campaign work off your plate. Install the tag and publish one form. About ten minutes. [Quickstart](/quickstart) Your positioning, proof and voice. This is the step that decides whether the agents write like you. [Load your Vault](/guides/load-your-vault) Scan what ChatGPT, Claude, Gemini and Perplexity say when a buyer asks about your category. [AI Visibility](/platform/ai-visibility/overview) Numbers, drafts and publishing from Slack, on a schedule. [SAM](/platform/sam/overview) After four weeks: forms live, a Vault the agents read, a visibility baseline, and a Monday digest you did not have to ask for. Goal: one clean record per buyer, routed and booked without a handoff. One row per buyer: identity, firmographics, behaviour, score. [Lead Data Layer](/platform/leads) Enrichment, signals and scoring run on every record as it lands. [Lead Agents](/platform/lead-agents/overview) HubSpot, Salesforce and Zoho, without a sync project. [System Agents](/platform/system-agents/overview) Qualify on the form, then put the right rep's calendar on the screen. [Routing rules](/platform/scheduling/routing) After four weeks: no manual enrichment, no round-robin spreadsheet, and a funnel you can show in a QBR. Goal: the contract. Pick the interface that matches what you are building. | If you want to | Go to | | -------------------------------------------------------------- | ------------------------------------------------------- | | Render Surface forms inside your own React or Next app | [Forms SDK](/build/forms-sdk/overview) | | Drive a workspace from Claude, Codex, Cursor or your own agent | [Surface MCP](/mcp-server/overview) | | Wire up one specific AI client | [Your AI agents](/build/agents/overview) | | Post an existing HTML form into Surface | [Webhooks and external forms](/build/webhooks/overview) | | Read forms and responses over HTTP | [API reference](/build/api-reference/api-keys) | | Fire browser events into GTM, GA4, Google Ads or Meta | [Events](/build/events/form-events) | Building with an AI assistant? Point it at [`/llms-full.txt`](https://docs.withsurface.com/llms-full.txt), which is the whole site as one Markdown file, then connect it with [Surface MCP](/mcp-server/setup). It can read the docs and call the API in the same session. --- URL: /concepts # Core Concepts ## Environment [#environment] The boundary everything else sits inside. A workspace can hold several environments (`production`, `staging`, one per brand or region), and **everything else belongs to exactly one of them**: leads, forms, the Vault, integrations, API keys. An API key or OAuth connection belongs to one environment, so an MCP tool call can never reach another one. `?tools=` changes which tools your assistant *loads*, never which data it may *touch*. See [Tool bundles](/mcp-server/tool-bundles). ## Lead [#lead] One person, one record, in the [Lead Data Layer](/platform/leads). Surface creates it the first time it can attach an identity to activity: a form completion, a webhook, an import. Later activity adds to the record instead of replacing it. A **response** is one submission of one form, and a lead may have many. Completion rate counts responses; pipeline counts leads. ## Vault [#vault] The environment's private Markdown knowledge base: positioning, product facts, customer proof, competitor notes, voice. Agents read it before they write. One crawl of your website starts a [Vault](/platform/vault/overview). ## Agent [#agent] A named worker with a job, a trigger, and something it writes to. Surface has four families: | Family | Reads | Writes | Runs when | | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------- | ------------------------------ | | [Lead Agents](/platform/lead-agents/overview) | Lead record, web | Lead fields, score | On capture, and on demand | | [Campaign Agents](/platform/campaign-agents/overview) | Vault, leads, CRM, web | Drafts, artifacts, CMS entries | On demand, on a schedule | | [System Agents](/platform/system-agents/overview) | Lead record, CRM | Your CRM and MAP | On change | | [SAM](/platform/sam/overview) | Forms, responses, leads, analytics, workflows, scores, the Vault, and whatever else its enabled capabilities cover | Content and drafts, behind an Approve card. Background jobs are read-only | When you ask, or on a schedule | ## Agent Action [#agent-action] **The metered unit of agent work.** Your plan is sized in agent actions. | | | | -------------------------- | ------------------------------------------------------------------------ | | Included per month | 15,000 on Agentic Marketing Operations. Custom above that, none on Basic | | Beyond the included volume | $0.20 per action | The [pricing page](https://www.withsurface.com/pricing) has the current numbers. What counts as one action is decided per agent. Check your usage in the app, or ask us, before you plan around a specific number. ## Artifact [#artifact] Something an agent produced that a person can review, edit, approve and publish: a draft post, a comparison page, a generated image. Artifacts keep version history. ## Segment [#segment] A saved, live query over leads: *"ICP fit ≥ 70, visited pricing in the last 14 days, no meeting booked"*. Campaigns target segments and agents run against them. Membership updates as records change, so a segment is never a frozen list. ## Profile [#profile] What an [AI Visibility](/platform/ai-visibility/overview) scan runs against: one domain, its positioning, its competitor set, and the prompts you track against it. Scores, cited sources and per-model breakdowns attach to the profile. Two words these docs avoid: **"contact"** (your CRM's object, which Surface syncs to rather than owns) and **"campaign"** meaning a channel. A Surface campaign is a plan with an audience, an outcome and measurement, see [Campaign Agents](/platform/campaign-agents/overview). --- URL: / # Surface Documentation Surface captures the demand already on your site, keeps one current record per buyer, and points agents at that record to research, score, route, schedule, write and publish. Tag installed and a first lead captured, in about ten minutes. Environment, Lead, Vault, Agent, Agent action, Artifact. Marketer, GTM engineer, developer. ## Where to Start [#where-to-start] Everything you'd open the app to do, done from Slack. **Beta.** Your positioning, proof and voice, in Markdown. Agents read it before they write. Where you show up when a buyer asks ChatGPT, Claude, Gemini or Perplexity. Branching forms, qualification, routing, and six ways to embed them. One record per buyer: identity, firmographics, behaviour, score. 128 tools. Point Claude, Codex, Cursor or your own agent at your workspace. ## If You Are an AI Agent [#if-you-are-an-ai-agent] Every page has a Markdown copy at `.md`. The page tree is indexed at [`/llms.txt`](https://docs.withsurface.com/llms.txt), and every page in one file is at [`/llms-full.txt`](https://docs.withsurface.com/llms-full.txt). To *act* on a workspace, start at [Surface MCP](/mcp-server/overview). Or start with [What is Surface?](/what-is-surface) --- URL: /quickstart # Quickstart You need a Surface environment and admin access to your site's ``. One script in ``, on every page. Traffic, funnel, attribution and AI referral data all come from it. ```html ``` Your site ID is in **Settings → Overview**. Per-platform instructions for Webflow, Framer, WordPress, Next.js, React and Unbounce are on [Surface Tag](/platform/traffic/surface-tag). Serve the tag from [your own domain](/platform/traffic/custom-domains) so ad blockers and Safari's cookie policy stop treating it as third-party. **Forms → New form**. Ask for an email and one qualifying question, nothing else. Publish. The [Form builder](/platform/forms/builder) covers steps, question types and logic. Pick a mode and paste the snippet. Inline is the default. Popup and slideover open from a button. The input-field trigger turns an email box you already have into the first step of a Surface form. ```html ``` Every mode is on [Embedding](/platform/forms/embedding). Fill your own form once with a real work email. It appears under **Leads** with company, industry and headcount filled in, and an AI lead score. Row there but enrichment empty? The email was a free provider. [Enrichment](/platform/leads/enrichment) resolves companies, not inboxes. Add one workflow: post to Slack, create a HubSpot contact, or fire a webhook. [Workflows](/platform/forms/workflows) · [Integrations](/platform/integrations) ## You Now Have [#you-now-have] * Every visit and AI referral in [Traffic analytics](/platform/traffic/analytics). * One enriched, scored row per person in the [Lead Data Layer](/platform/leads). * Page views → form views → starts → completions → qualified → meetings in the [Conversion funnel](/platform/traffic/conversion-funnel). ## Next Steps [#next-steps] Crawl your own site to fill the knowledge base agents write from. Leads land where your reps already work. Find out what ChatGPT says about you today. --- URL: /what-is-surface # What Is Surface? Surface is a marketing system with two halves that feed each other. **The infrastructure half** sits on your website and captures demand: a tag that records who arrives and where from, forms that branch on the answers, scheduling that books the qualified ones, and a lead record that keeps what all of it learned. **The agent half** reads that record and does the work: researching and scoring leads, keeping your CRM current, finding the questions buyers ask AI engines, and writing the campaigns that answer them. ## What It Replaces [#what-it-replaces] | You probably run | Surface does it as | | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------ | | Typeform / HubSpot forms | [Dynamic Lead Forms](/platform/forms/builder) | | Chili Piper / Calendly | [Intelligent Scheduling](/platform/scheduling/overview), with no per-seat pricing | | Manual enrichment runs | [Lead Agents](/platform/lead-agents/overview). You can also [connect the provider you already pay for](/platform/integrations) | | An AEO/GEO monitoring tool | [AI Visibility](/platform/ai-visibility/overview) | | A content agency retainer | [Campaign Agents](/platform/campaign-agents/overview) | | GA4 dashboards nobody trusts | [Traffic Intelligence](/platform/traffic/analytics) | Most teams start with the tag or forms, then add agents. ## Where the Intelligence Comes From [#where-the-intelligence-comes-from] The [Surface Tag](/platform/traffic/surface-tag) records who arrives, from where, and what they do. Visitors who came from an answer engine are reported that way instead of as "direct". Every capture becomes one record in the [Lead Data Layer](/platform/leads): enriched, scored, stamped with the journey that produced it. Outcomes (meetings, closed deals) come back to that record. The [Vault](/platform/vault/overview) is your own words: positioning, proof, objections, voice. Agents read it before they write. ## What "Agentic" Means Here [#what-agentic-means-here] Agents in Surface: * **run without being asked**: enrichment and scoring fire on capture, and the competitor agent checks on its own timer. * **write to real systems**: the lead record, your CRM, the CMS, your calendar. * **stop for a human before they publish or change anything**. See [SAM's approval gate](/platform/sam/limits). * **are metered**: an *agent action* is the unit your plan is sized in, see [Core concepts](/concepts#agent-action). We'll run a traffic audit and an AI visibility scan on your domain before the call. --- URL: /whats-new # What's New Every release, newest first, with screenshots. The longer pieces: agentic GTM, AI search, lead quality. ## Recently Added to These Docs [#recently-added-to-these-docs] | Section | Status | | ------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | | [SAM](/platform/sam/overview) | Beta, documented in full | | [Vault](/platform/vault/overview) | Beta, new section | | [Campaign Agents](/platform/campaign-agents/overview) | New section | | [AI Visibility](/platform/ai-visibility/overview) | New section | | [Lead Agents](/platform/lead-agents/overview) · [System Agents](/platform/system-agents/overview) | New sections | | [Intelligent Scheduling](/platform/scheduling/overview) | New section | | [Your AI agents](/build/agents/overview) | New section: Claude, Codex, Grok, and any MCP client | | [Embedding](/platform/forms/embedding) | 56 per-platform pages collapsed onto one page per mode | ## Following Along in Your Tools [#following-along-in-your-tools] * **In Slack**: [SAM](/platform/sam/schedules) can post a weekly digest of your own numbers into a channel. * **In an agent**: the docs publish [`/llms.txt`](https://docs.withsurface.com/llms.txt) and per-page Markdown at `.md`, so an assistant reads current behaviour instead of guessing from training data. --- URL: /build # Build on Surface Three ways in, depending on what you are building. For the MCP server, see the [MCP](/mcp-server/overview) tab. Claude, Codex, Grok, Cursor, Windsurf, and anything else that speaks MCP. Render a Surface form from your own markup and styles. Post any HTML form into Surface, and push Surface data anywhere else. ## Reference [#reference] Keys, forms and responses over HTTP. Browser events for GTM, GA4, Google Ads and Meta Ads. ## Which One Do I Want? [#which-one-do-i-want] | Goal | Use | | ------------------------------------------------------- | ------------------------------------------------------ | | "My assistant should answer questions about our funnel" | [MCP, read-only](/mcp-server/tool-bundles) | | "My assistant should build and publish forms" | [MCP, forms bundle](/mcp-server/overview) | | "The form must be part of my React app, not an iframe" | [Forms SDK](/build/forms-sdk/quickstart) | | "I have an existing HTML form I can't replace" | [External forms](/build/webhooks/create-external-form) | | "Send every submission to our own service" | [Webhooks](/build/webhooks/overview) | | "Fire a conversion event into Google Ads" | [Events](/build/events/google-ads-tracking) | | "Read responses from a cron job" | [API reference](/build/api-reference/api-keys) | Tool access is scoped to the credential's environment. Add `?readonly=1` and an agent cannot write. See [Tool bundles](/mcp-server/tool-bundles). --- URL: /embedding/website-editors # Embed Surface Forms in Your Website Builder or Framework Pick your website builder or framework. Each one has the same six steps: install the Surface Tag, then embed the form in whichever mode you want. For the modes themselves, and for hosts not listed here, see [Embedding a Surface Form](/platform/forms/embedding). Add Surface Forms to your Framer site with custom code components Integrate forms into your Webflow site using custom embeds Embed forms on your WordPress site with a plugin or custom code Embed Surface Forms in your React.js applications Add Surface Forms to your Next.js applications Integrate forms with your Unbounce landing pages Use raw HTML/JavaScript for any website or platform ## Don't See Your Platform Listed? [#dont-see-your-platform-listed] Surface Forms can be integrated with any website that supports custom HTML/JavaScript. Check out our [Inline Embedding](/platform/forms/embedding/inline) guide for general integration instructions. All integrations require the [Surface Tag](/platform/traffic/surface-tag) to be installed first. --- URL: /guides/build-an-sdk-form # Build a Form with the Forms SDK You will build a demo-booking form on a page you host: two question steps, a branch that disqualifies small companies, a scheduler step, and a thank-you screen. The form record on Surface is the data model, your HTML is the presentation, and the SDK binds the two ([overview](/build/forms-sdk/overview)). ## Prerequisites [#prerequisites] * A Surface environment. * The [SDK package](https://www.npmjs.com/package/@surface-labs/forms-sdk) installed: `npm install @surface-labs/forms-sdk`. * Ideally the [Surface MCP server](/mcp-server/setup) connected to your AI assistant; without it, copy IDs from the dashboard. ## Step 1: Create the Form Record [#step-1-create-the-form-record] Ask your assistant, or call the tools yourself: ``` create_form with sdk: true name: "Demo booking" steps: 1. "About you": IdentityInfo (first name, last name, work email) 2. "Company": MultipleOptionsQuestion "How large is your team?" options: "1-10", "11-50", "51-200", "200+" 3. "Book a time": CalendlyScreen (your Surface scheduler) 4. "Thanks" (endStepKind: thank_you): Header "You're booked!" 5. "Not a fit" (endStepKind: disqualified): Header "Thanks for your interest" ``` * Give every question real question text; the responses table uses it as the column label. * Ending steps need at least one component; a `Header` is fine. * Link the scheduler's prefill to the identity step (`linkNameToStep`, `linkEmailToStep`). * Save the `formId` and `previewToken` from the reply. The dashboard builds the same record by hand: Forms, Create New Form, Build SDK form. ## Step 2: Get the Binding Map [#step-2-get-the-binding-map] ``` get_sdk_binding_map formId: ``` The reply lists every step and question with `questionId`, `componentType`, `fieldNames`, option keys, and `answerShape`, plus `environmentId`, `apiBaseUrl`, and a ready-to-paste `init` snippet. Never retype IDs from memory. ## Step 3: Write the Page [#step-3-write-the-page] ```html ``` Replace every `STEP_*` and `Q_*` placeholder with real IDs from the binding map, and keep the radio `value` attributes byte-identical to the record's option keys. Every container after the first is `hidden`. The choice question binds as a group (no `data-field-name` on options), the scheduler question has no binding, and both endings have their own container. ## Step 4: Boot, Branch, and Mount the Scheduler [#step-4-boot-branch-and-mount-the-scheduler] ```js import { SurfaceForms, mountScheduler } from "@surface-labs/forms-sdk"; const form = await SurfaceForms.init({ environmentId: "ENV_ID", formId: "FORM_ID", apiBaseUrl: "API_BASE_URL", // from get_sdk_binding_map container: document.querySelector("#demo-form"), emailValidation: true, // annotate deliverability; never blocks preview: true, // remove before deploying previewToken: "PREVIEW_TOKEN", }); document.querySelector("#demo-form").hidden = false; // The branch: small teams get the disqualified ending. document.querySelector("#company-continue").addEventListener("click", () => { const answer = form.state().answers["STEP_COMPANY"]?.["Q_SIZE"]; const picked = answer?.choices?.find((c) => c.value)?.key; if (!picked) return; // require an answer if (picked === "1-10") form.disqualify(); else form.next(); }); // Mount once, into the still-hidden step container. mountScheduler({ form, container: document.querySelector("#booking"), onEvent(e) { if (e.type === "booking_confirmed") form.submit(); }, }); ``` The branch is code-driven, so add `data-surface-nav="js"` to the ``. Everything else (answer capture, partial saves, booking persistence, identity, journey tracking, busy state) is the SDK's job. ## Step 5: Validate the Markup [#step-5-validate-the-markup] ``` validate_form_html formId: html: containerSelector: "#demo-form" ``` Fetch the page exactly as a visitor receives it; for a framework page, curl the dev server output. Fix every blocker and re-run until clean. ## Step 6: Walk It in Preview [#step-6-walk-it-in-preview] With `preview: true` and the `previewToken`, the page serves the draft record and writes nothing: walk both branches, book a synthetic meeting, confirm both endings render. ## Step 7: Publish and Deploy [#step-7-publish-and-deploy] ``` publish_form formId: ``` Remove `preview: true` and `previewToken`, then deploy. ## Step 8: Verify End to End [#step-8-verify-end-to-end] Submit one real test response on the deployed page, then read it back: ``` list_responses formId: get_response responseId: ``` Confirm every answer landed, the choice answer carries the structured list, the booking has `eventScheduled: true`, and the metadata shows `surfaceTagStatus: "sdk"`. ## Where to Go Next [#where-to-go-next] Every attribute and inference rule. Render the form from your components. The rules that keep SDK forms correct. Symptom to cause to check. --- URL: /guides/control-form-logic-based-on-api # API Based Conditional Logic Use **External API Data** in the **Logic** tab to create branching form flows based on your own API response (for example: auth checks, eligibility checks, plan gating, or enrichment). New to conditional logic? Start with [Conditional Logic](/platform/forms/conditional-logic). ## Step 1: Open the Logic Tab [#step-1-open-the-logic-tab] 1. Open your form in the Surface editor. 2. Click **Logic** at the top. 3. Select the step where you want to evaluate routing (this is typically the step where the user clicks “Next”). Logic tab in the Surface form builder ## Step 2: Add an HTTP Request [#step-2-add-an-http-request] 1. With your step selected, click **+ HTTP Request**. 2. Configure the request: * **URL**: your endpoint (for example, `https://api.yourdomain.com/eligibility`) * **Method**: `GET` or `POST` depending on your API * **Params / Headers**: add any required values * **Body (POST)**: send JSON, using form variables if needed Add HTTP Request in the Logic tab You can use form variables in the URL, Params, Headers, and Body. ## Step 3: Map Fields from the API Response [#step-3-map-fields-from-the-api-response] Configure API response mapping automatically or manually Map values from the JSON response so they are available as **External API Data**. ### Automatically Configure the API Response [#automatically-configure-the-api-response] Automatically Configure the API Response 1. Click on "Configure automatically" button. 2. Surface reads the API response and suggests fields you can map. 3. Select the fields you want to map and click on "Save" button. ### Manually Configure the API Response [#manually-configure-the-api-response] Manually Configure the API Response 1. Click on "Configure manually" button. 2. You select the fields to extract from the JSON response yourself. ## Step 4: Create an Advanced Routing Rule Using External API Data [#step-4-create-an-advanced-routing-rule-using-external-api-data] Routing rule checking External API Data equals true 1. Open **Advanced Routing** for the step. 2. Set **Jump to step** to the step you want to send the user to when the condition is met. 3. Under **IF**, set: * **Source**: `External API Data` * **Condition**: choose the field you mapped (for example, `isPriorityLead`) and compare it to the expected value (for example, `true`) ### Example: Only Proceed If isPriorityLead Is True [#example-only-proceed-if-isprioritylead-is-true] * **IF**: `External API Data.isPriorityLead` equals `true` * **THEN**: Jump to `Step: 1 (Book a Demo)` * **ELSE**: Keep default routing to next step (or jump to a “Not eligible” / “Invalid” step) Testing External API Data based routing in a published form ## Step 5: Publish and Test [#step-5-publish-and-test]