Developer documentation
Embed a SalesHose form anywhere
SalesHose builds conversational lead-qualification forms that score, route, and book your leads. This is everything you (or an AI coding tool) need to drop one into any website and read its data over a public REST API.
Quickstart
Every form has a slug (e.g. demo). Drop these two lines where you want the form to appear:
<div data-saleshose="demo"></div>
<script src="https://saleshose.com/embed.js" async></script>
That's it. The form loads in a sandboxed iframe, so it never clashes with your site's CSS or JavaScript. Replace demo with your own form's slug (find it in the builder, or in the form URL saleshose.com/f/your-slug).
Embed modes
Inline
Renders the form inside a container on the page. Set an optional data-height (default 560px).
<div data-saleshose="demo" data-height="600"></div>
<script src="https://saleshose.com/embed.js" async></script>
Popup button
Renders a button; the form opens in a centered modal.
<div data-saleshose="demo" data-mode="popup" data-label="Talk to sales"></div>
<script src="https://saleshose.com/embed.js" async></script>
Chat bubble (one line)
A floating launcher in the bottom-right corner β no container needed. Ideal for pasting into any site once.
<script src="https://saleshose.com/embed.js" data-saleshose="demo" data-mode="bubble" data-label="π¬ Chat" async></script>
| Attribute | Where | Values |
|---|---|---|
data-saleshose | div or script | your form slug (required) |
data-mode | div or script | inline (default for div) Β· popup Β· bubble (default for script) |
data-label | div or script | button / bubble text |
data-height | div (inline) | pixels, default 560 |
Platform guides
| Platform | How |
|---|---|
| WordPress | Add a Custom HTML block and paste the snippet. (Classic editor: Text tab.) |
| Shopify | Add a Custom Liquid section (or an HTML block in a page) and paste the snippet. |
| HubSpot | Drag an Embed / Rich text β Source code module onto the page and paste the snippet. |
| Webflow | Drop an Embed element and paste the snippet. |
| Framer / Wix / Squarespace | Use the platform's Embed / Custom Code block. |
| Plain HTML / any site | Paste anywhere in your HTML. |
React / Next.js
import { useEffect } from "react";
export default function SalesHoseForm({ slug }) {
useEffect(() => {
const s = document.createElement("script");
s.src = "https://saleshose.com/embed.js";
s.async = true;
document.body.appendChild(s);
return () => { s.remove(); };
}, []);
return <div data-saleshose={slug} />;
}
JavaScript API
Once embed.js has loaded, a global SalesHose object is available:
// Open any form in a modal
SalesHose.open("demo");
// Render programmatically
SalesHose.render({ slug: "demo", target: "#lead-form", mode: "inline" });
SalesHose.render({ slug: "demo", mode: "bubble", label: "Need a quote?" });
// Close the modal
SalesHose.close();
When a form is submitted inside an embed, it posts a message to the host page you can listen for:
window.addEventListener("message", (e) => {
if (e.data && e.data.type === "saleshose:submitted") {
console.log("Lead captured for", e.data.slug, "score", e.data.score);
}
});
Public REST API
No key required for the public endpoints below. Base URL https://saleshose.com.
Get a form's config
GET /api/forms/{slug}
200 β { "slug": "demo", "title": "β¦", "config": { "blocks": [...], "theme": {...} } }
Submit a response
Send the answers keyed by each block's name. Returns the computed lead score and the resolved ending (including any assigned rep / booking link).
POST /api/forms/{slug}/responses
Content-Type: application/json
{
"data": { "name": "Jane", "email": "jane@acme.com", "budget": "β¬20k+" },
"completed": true,
"meta": { "utm_source": "google" }
}
200 β {
"ok": true,
"id": "β¦",
"score": 105,
"ending": { "title": "β¦", "book": { "url": "https://cal.com/rep/intro" }, "rep": "Alice" }
}
"id" with "completed": false to capture partial responses, then re-POST the same id with "completed": true to finish it.Track funnel events (optional)
POST /api/forms/{slug}/events
{ "kind": "view" | "start" | "complete", "session": "β¦" }
Connect your stack
Every completed lead (and every booking) can be pushed to where your team works β set these per form in Builder β Settings β Delivery & connections.
- Webhook β POSTs the lead as JSON to any URL. Point it at Zapier, Make, or n8n to reach thousands of apps and CRMs (HubSpot, Salesforce, Sheets, Notionβ¦).
- Slack β paste a Slack incoming webhook to get formatted lead alerts in a channel (optionally hot-leads-only).
- Inline booking β route qualifying leads onto a rep's Cal.com / Calendly inside the form.
Verifying webhook signatures
If you set a signing secret, each webhook includes an X-SalesHose-Signature: sha256=<hex> header β an HMAC-SHA256 of the raw request body keyed with your secret. Recompute it server-side and compare to confirm the request really came from SalesHose.
// Node example
import crypto from "node:crypto";
const expected = "sha256=" + crypto.createHmac("sha256", SECRET)
.update(rawBody).digest("hex");
if (expected !== req.headers["x-saleshose-signature"]) reject();
Fire conversion events only for qualified leads
Make ad spend optimise toward your best leads. SalesHose can trigger your existing ad pixel (Meta Pixel, Google Ads / GA4, or GTM dataLayer) on the host page β by default only when a lead qualifies (score β₯ your threshold, set in Builder β Settings β Conversion tracking). Add one attribute to your embed:
<div data-saleshose="demo" data-conversion-event="Lead"></div>
<script src="https://saleshose.com/embed.js" async></script>
When a qualified lead completes, SalesHose calls fbq('track','Lead'), gtag('event','Lead'), and pushes to dataLayer (whichever are present on your page). Choose when it fires with data-conversion-on: qualified (default), complete (any submission), or booked (only when a meeting is booked).
Wiring it yourself? Listen for the message:
window.addEventListener("message", (e) => {
if (e.data?.type === "saleshose:submitted" && e.data.qualified) {
fbq("track", "Lead"); // your pixel β only for qualified leads
}
});
Pre-fill & hidden fields
Pass URL query params to pre-fill answers and capture extra context. Params that match a question's name pre-fill that answer; anything else is stored on the response as hidden fields (alongside captured utm_*).
https://saleshose.com/f/your-slug?email=jane@acme.com&plan=pro&ref=newsletter
This works for embeds too β embed.js forwards the host page's query string into the form, so UTM attribution and pre-fill carry through automatically.
Build with AI
Building a SalesHose integration with an AI coding tool (Cursor, v0, Lovable, Claude, Copilotβ¦)? Point it at these machine-readable references:
- /llms.txt β product + endpoint summary for LLMs
- /openapi.json β OpenAPI 3 spec for the public REST API
Or paste this prompt:
Add a SalesHose conversational lead form to my site.
Embed it with:
<div data-saleshose="MY_SLUG"></div>
<script src="https://saleshose.com/embed.js" async></script>
Modes: data-mode="inline|popup|bubble". JS API: SalesHose.open(slug),
SalesHose.render({slug,target,mode,label}). It loads in an iframe.
Full docs: https://saleshose.com/docs