URL: https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/mcp-server/tool-bundles). ## Lead [#lead] One person, one record, in the [Lead Data Layer](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/platform/lead-agents/overview) | Lead record, web | Lead fields, score | On capture, and on demand | | [Campaign Agents](https://www.withsurface.com/docs/platform/campaign-agents/overview) | Vault, leads, CRM, web | Drafts, artifacts, CMS entries | On demand, on a schedule | | [System Agents](https://www.withsurface.com/docs/platform/system-agents/overview) | Lead record, CRM | Your CRM and MAP | On change | | [SAM](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/platform/campaign-agents/overview). --- URL: https://www.withsurface.com/docs # Surface Documentation * Read these docs from Claude, Cursor or any MCP client with the [docs MCP server](https://www.withsurface.com/docs/mcp-server/docs-mcp). Search, list and fetch, no auth, no key. * *Act* on a workspace with [Surface MCP](https://www.withsurface.com/docs/mcp-server/overview): 132 tools in 17 families, including a new read-only [campaigns family](https://www.withsurface.com/docs/mcp-server/tools#campaigns). * The Platform section is regrouped by what each thing does: agents, analytics, infrastructure, primitives. ## What is Surface? [#what-is-surface] 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. It replaces the seam between your forms, your enrichment, your scheduler and your CRM with a single record everything reads and writes. [What is Surface?](https://www.withsurface.com/docs/what-is-surface) is the longer answer. ## Start with the Outcome You Want [#start-with-the-outcome-you-want] Tag installed and a first lead captured, in about ten minutes. Research, enrichment, signal and scoring on every record as it lands. Where you appear in ChatGPT, Claude, Gemini and Perplexity, and where you do not. Research, a plan and drafts as artifacts, with a human in front of publish. Qualify, route and book in one path. No per-seat pricing, no booking caps. 132 tools in 17 families, over one MCP endpoint. ## Not Sure Which of Those You Are? [#not-sure-which-of-those-you-are] ## Explore the Platform [#explore-the-platform] [SAM](https://www.withsurface.com/docs/platform/sam/overview) in Slack · [Lead Agents](https://www.withsurface.com/docs/platform/lead-agents/overview) on every record · [System Agents](https://www.withsurface.com/docs/platform/system-agents/overview) on your CRM · [Campaign Agents](https://www.withsurface.com/docs/platform/campaign-agents/overview) on your content [AI Visibility](https://www.withsurface.com/docs/platform/ai-visibility/overview) across answer engines · [Traffic Intelligence](https://www.withsurface.com/docs/platform/traffic/surface-tag): the tag, content analytics and the conversion funnel [Vault](https://www.withsurface.com/docs/platform/vault/overview) for positioning and voice · [Dynamic Lead Forms](https://www.withsurface.com/docs/platform/forms/builder) · [Intelligent Scheduling](https://www.withsurface.com/docs/platform/scheduling/overview) [Lead Data Layer](https://www.withsurface.com/docs/platform/leads), the record everything else reads and writes · [Integrations](https://www.withsurface.com/docs/platform/integrations) ## Start Where Your Job Starts [#start-where-your-job-starts] | Your job | Read in this order | | ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- | | **Marketing** | [Quickstart](https://www.withsurface.com/docs/quickstart) → [Load your Vault](https://www.withsurface.com/docs/guides/load-your-vault) → [AI Visibility](https://www.withsurface.com/docs/platform/ai-visibility/overview) → [SAM](https://www.withsurface.com/docs/platform/sam/overview) | | **GTM / RevOps** | [Lead Data Layer](https://www.withsurface.com/docs/platform/leads) → [Lead Agents](https://www.withsurface.com/docs/platform/lead-agents/overview) → [Routing rules](https://www.withsurface.com/docs/platform/scheduling/routing) | | **Developers** | [Forms SDK](https://www.withsurface.com/docs/build/forms-sdk/quickstart) → [Surface MCP](https://www.withsurface.com/docs/mcp-server/overview) → [Webhooks](https://www.withsurface.com/docs/build/webhooks/overview) | ## Understand How Surface Works [#understand-how-surface-works] Environment, Lead, Vault, Agent, Agent action, Artifact. The six words the rest of these docs assume. Every way a person enters the Lead Data Layer, and what is known about them when they do. Where the line between "drafted" and "published" sits, and who moves it. ## 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://withsurface.com/docs/llms.txt), and every page in one file is at [`/llms-full.txt`](https://withsurface.com/docs/llms-full.txt). To read these docs as tools instead, connect the [docs MCP server](https://www.withsurface.com/docs/mcp-server/docs-mcp). To *act* on a workspace, start at [Surface MCP](https://www.withsurface.com/docs/mcp-server/overview). --- URL: https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/platform/traffic/surface-tag). Serve the tag from [your own domain](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/platform/leads/enrichment) resolves companies, not inboxes. Add one workflow: post to Slack, create a HubSpot contact, or fire a webhook. [Workflows](https://www.withsurface.com/docs/platform/forms/workflows) · [Integrations](https://www.withsurface.com/docs/platform/integrations) ## You Now Have [#you-now-have] * Every visit and AI referral in [Traffic analytics](https://www.withsurface.com/docs/platform/traffic/analytics). * One enriched, scored row per person in the [Lead Data Layer](https://www.withsurface.com/docs/platform/leads). * Page views → form views → starts → completions → qualified → meetings in the [Conversion funnel](https://www.withsurface.com/docs/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: https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/platform/forms/builder) | | Chili Piper / Calendly | [Intelligent Scheduling](https://www.withsurface.com/docs/platform/scheduling/overview), with no per-seat pricing | | Manual enrichment runs | [Lead Agents](https://www.withsurface.com/docs/platform/lead-agents/overview). You can also [connect the provider you already pay for](https://www.withsurface.com/docs/platform/integrations) | | An AEO/GEO monitoring tool | [AI Visibility](https://www.withsurface.com/docs/platform/ai-visibility/overview) | | A content agency retainer | [Campaign Agents](https://www.withsurface.com/docs/platform/campaign-agents/overview) | | GA4 dashboards nobody trusts | [Traffic Intelligence](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/platform/leads): enriched, scored, stamped with the journey that produced it. Outcomes (meetings, closed deals) come back to that record. The [Vault](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/platform/sam/limits). * **are metered**: an *agent action* is the unit your plan is sized in, see [Core concepts](https://www.withsurface.com/docs/concepts#agent-action). We'll run a traffic audit and an AI visibility scan on your domain before the call. --- URL: https://www.withsurface.com/docs/build # Build on Surface Three ways in, depending on what you are building. For the MCP server, see the [MCP](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/mcp-server/tool-bundles) | | "My assistant should build and publish forms" | [MCP, forms bundle](https://www.withsurface.com/docs/mcp-server/overview) | | "The form must be part of my React app, not an iframe" | [Forms SDK](https://www.withsurface.com/docs/build/forms-sdk/quickstart) | | "I have an existing HTML form I can't replace" | [External forms](https://www.withsurface.com/docs/build/webhooks/create-external-form) | | "Send every submission to our own service" | [Webhooks](https://www.withsurface.com/docs/build/webhooks/overview) | | "Fire a conversion event into Google Ads" | [Events](https://www.withsurface.com/docs/build/events/google-ads-tracking) | | "Read responses from a cron job" | [API reference](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/mcp-server/tool-bundles). --- URL: https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/platform/forms/embedding/inline) guide for general integration instructions. All integrations require the [Surface Tag](https://www.withsurface.com/docs/platform/traffic/surface-tag) to be installed first. --- URL: https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/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: https://www.withsurface.com/docs/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](https://www.withsurface.com/docs/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]