Example file
05-visitor-journey.html
Plays the part of an AI assistant, asking a question and a follow-up, registering interest, sharing requirements and getting a link to a specialist.
To try this page, download it, replace the placeholders and put it on a test page of your website. Opening the file from your computer won't work, because the embeds check the website address they're on.
<!--
What an AI assistant in the visitor's browser might do with your tools,
played out by this page: a question and a follow-up in the same
conversation, then register_interest, share_requirements and
talk_to_a_specialist. Each tool takes what the one before it returned.
Works in any browser (the wrapper from 03-inspect-and-call.html stands in
when there is no WebMCP). Replace wmk_YOUR_KEY with your integration's key.
This saves real data to your account: a conversation in your inbox, and a
contact and a lead in your CRM. Use test details and tidy up afterwards.
-->
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>WebMCP: a visitor's journey</title>
<style>
pre { white-space: pre-wrap; }
</style>
</head>
<body>
<h1>A visitor's journey through the tools</h1>
<p>
This page plays the part of an AI assistant helping a visitor. It asks a question and a follow-up in the
same conversation, registers the visitor's interest, shares what they're looking for, and gets a link to a
specialist. Each step uses what the step before returned.
</p>
<p>
<strong>This saves real data to your Subcontext account</strong>: a conversation in your inbox, and a
contact and a lead in your CRM. Answering questions runs your AI agent and uses AI credit.
</p>
<form id="journey">
<p><label>Visitor name<br><input name="name" value="Sam Visitor" size="40"></label></p>
<p><label>Visitor email<br><input name="email" type="email" value="sam.visitor@example.com" size="40"></label></p>
<p><label>Question<br><input name="question" value="Do you offer joint life cover?" size="60"></label></p>
<p><label>Follow-up<br><input name="followUp" value="Is there an upper age limit?" size="60"></label></p>
<p><button>Run the journey</button></p>
</form>
<ol id="steps"></ol>
<script>
// Record the tools the script offers (with a stand-in when the browser has
// no WebMCP). 03-inspect-and-call.html explains this.
var tools = {}
var browser = document.modelContext || navigator.modelContext
Object.defineProperty(document, 'modelContext', {
configurable: true,
value: {
registerTool: function (tool, options) {
tools[tool.name] = tool
options.signal.addEventListener('abort', function () { delete tools[tool.name] })
return browser ? browser.registerTool(tool, options) : Promise.resolve()
},
unregisterTool: function (name) {
if (browser && browser.unregisterTool) return browser.unregisterTool(name)
}
}
})
// Calls one tool the way an AI assistant would, and shows the input and result.
// Gives back the tool's data, or null when the tool isn't offered or the call fails.
async function step(name, input) {
var item = document.createElement('li')
item.innerHTML = '<strong></strong><pre></pre>'
item.firstChild.textContent = name
var detail = item.lastChild
document.getElementById('steps').appendChild(item)
if (!tools[name]) {
detail.textContent = 'Skipped: this tool isn\'t offered (tick it on the integration).'
return null
}
detail.textContent = 'input: ' + JSON.stringify(input) + '\n...'
try {
var data = await tools[name].execute(input)
detail.textContent = 'input: ' + JSON.stringify(input) + '\nresult: ' + JSON.stringify(data, null, 2)
return data
} catch (error) {
detail.textContent = 'input: ' + JSON.stringify(input) + '\nerror: ' + error.message
return null
}
}
var form = document.getElementById('journey')
form.addEventListener('submit', async function (event) {
event.preventDefault()
document.getElementById('steps').textContent = ''
// A question, then a follow-up in the same conversation.
var first = await step('answer_question', { question: form.question.value })
await step('answer_question', { question: form.followUp.value, conversation_id: first ? first.conversation_id : undefined })
// Who they are. An email or a phone number is required.
var lead = await step('register_interest', {
name: form.name.value,
email: form.email.value,
message: 'Asked about joint life cover'
})
// What they want, added to that contact. It never creates a contact,
// so it fails until register_interest has run.
await step('share_requirements', {
contact_id: lead ? lead.contact_id : undefined,
email: lead ? undefined : form.email.value,
requirements: { cover_type: 'joint life', budget: '40 a month', timescale: 'within a month' }
})
// Where a person can take over.
await step('talk_to_a_specialist', {})
})
</script>
<!-- The snippet as usual, after the wrapper. Replace wmk_YOUR_KEY with your integration's key (starts wmk_).
In the dashboard: Organisation > Agent access > Manage WebMCP tools, then open the integration. -->
<script id="webmcp-embed-script" src="https://js.subcontext.com/webmcp-latest.js"
data-key="wmk_YOUR_KEY" async></script>
</body>
</html>