api | install-astro | install-caddy | install-cloudflare | install-express | install-js-tag | install-netlify | install-nginx | install-shopify | install-squarespace | install-sveltekit | install-vercel-next | install-webflow | install-wix | install-wordpress | mcp | outcomes | privacy | quickstart | troubleshooting
Outcomes connect AI attribution to business results. Each outcome is stored against the site with its first-touch source, so reports show "ChatGPT: 3 inquiries, 1 booked, $850".
POST /v1/outcomesUse this from your backend, CRM, or automation (Zapier, Make, n8n). Value and status are accepted only with an API key.
curl -s -X POST https://signal.ambit.agency/v1/outcomes \
-H "Authorization: Bearer $AMBIT_SIGNAL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"site_id": "st_YOURSITEID",
"type": "booking",
"id": "INV-1042",
"status": "confirmed",
"value": 850,
"src": {"provider": "openai", "via": "utm:chatgpt.com", "landing": "/private-dining"}
}'
| Field | Required | Notes |
|---|---|---|
site_id |
yes | Must belong to the key's account. |
type |
yes | lead, booking, sale or signup. |
id |
yes | Your id for this outcome (max 100 chars). Re-sending the same type + id updates it (for example when a lead becomes a booking). |
status |
no | Counted as converted: booked, won, closed_won, confirmed, deposit_received, menu_planning, prep, in_progress, completed, invoiced, paid, active, paused. Counted as lost: cancelled, inactive. Anything else (for example new, open, proposal_sent) is open pipeline. |
value |
no | Number, in the site's currency. Converted outcomes report as booked value; open ones as open quotes. |
src |
no | The first-touch record. Take it from the form's hidden ambit_src field (JSON string, parse it) or from window.ambitSrc(). Keys: provider, via, landing, ts, tz, screen, lang. provider is one of openai, perplexity, google, microsoft, anthropic, meta, xai, or empty. |
Once an outcome has a known source it keeps it: a later update without src does not erase it.
window.ambitSignal.outcomeWith the JS tag on the page:
window.ambitSignal.outcome("lead", "form-" + Date.now());
Browser calls are accepted only from the site's own domain (Origin check) and are rate limited. They cannot set value or status and cannot overwrite an outcome your server already reported. Use them to count leads on sites with no backend; report value from the server.
The JS tag adds a hidden input ambit_src to every form on the page. Its value is a JSON string such as {"provider":"openai","via":"utm:chatgpt.com","landing":"/","ts":1790170000000}. Make sure your form handler keeps that field, then forward it as src.
ambit_src field with each submission automatically (Forms tab shows it)./v1/outcomes with type: "lead", id = the submission id, src = the parsed ambit_src field.ambit_src.<form> elements. For the iframe embed, add in the form embed options: onFormReady: function(f){ var i=f.querySelector('input[name="ambit_src"]'); if(i) i.value=JSON.stringify(window.ambitSrc()); }.ambit_src to src.Gravity Forms saves only its own fields, so use a Hidden field rather than the auto-added input.
1. Add a Hidden field labelled ambit_src. Under Appearance, set Custom CSS Class to ambit-src.
2. Install the JS tag, and in the theme footer add:
```html
``
3. In agform_after_submissionhook,wp_remote_postto/v1/outcomeswithtype: "lead",id= the entry id, andsrc= the decoded hidden field. Keep the API key inwp-config.phpas a constant (AMBIT_SIGNAL_API_KEY`), never in the database or theme.
ambit_src arrives with each submission./v1/outcomes as above.curl -s -H "Authorization: Bearer $AMBIT_SIGNAL_API_KEY" \
"https://signal.ambit.agency/v1/sites/st_YOURSITEID/report?days=30" | python3 -c "import sys,json; print(json.load(sys.stdin)['report']['inquiries'])"