Skip to navigation

Add the embed

The embed is a small script that runs on your quote pages. When someone continues to payment, it asks HumanApproved whether the purchase can proceed. Customers buying for themselves proceed as they would normally. When an AI agent is buying, the step pauses and the agent is shown a link to pass to the customer, who approves the purchase.

You need a published product, a test publishable key (pk_test_…) and your test website on the product’s allowed websites. See Set up a product and Keys and environments.

1

Load the script on every page of the journey

Put the embed in the shared layout of your quote journey, so it’s on every page, not only the payment step. The checks look at how the whole journey was completed, from the first page the script is on: a script loaded only on the payment page has little to measure.

<!-- On every page of the quote journey, in your shared layout -->
<script src="https://cdn.beopen.com/approvals-embed/1.5.0/embed.js"
integrity="sha384-…" crossorigin="anonymous" async></script>
<!-- On the page with the step that continues to payment: your own file, with the code below -->
<script src="/js/checkout-approvals.js" defer></script>

Copy the tag from the Embed page in the portal: it has the current version and its integrity hash filled in.

  • Pinned with SRI. The version is in the address and the browser checks the file against the hash, so your pages only run the file you tested. There’s no “latest” address: to upgrade, change the version and the hash together.
  • Keep crossorigin="anonymous". The browser only checks the hash on a script loaded that way.
  • async means the script never holds up your page.

If your site sends a Content Security Policy, allow the CDN and the API: see Content Security Policy.

2

Protect the step before payment

In your own file (here /js/checkout-approvals.js, served from your site like your other scripts), call protect:

checkout-approvals.js
window.HumanApproved = window.HumanApproved || { q: [] };
HumanApproved.q.push(["protect", {
key: "pk_test_…", // your publishable key
quote: "HTA-4471920", // your quote reference: 1–128 characters, not personal data
before: "#continue-to-payment", // the button, link or form that continues to payment
quoteDetails: () => ({
quote: {
policyholder: { firstName: "Sam" },
destination: "Japan",
dates: { from: "2026-12-03", to: "2026-12-17" },
travellers: 2,
cover: "Comprehensive",
excess: 200,
premium: { amount: 412.6, currency: "GBP" },
},
mobile: "+44 7700 900482", // the customer's own mobile: the code goes here
}),
}]);

The queue works whichever loads first, your file or the embed. Keep the call in a file rather than an inline <script>, so a strict CSP doesn’t block it.

before is a CSS selector for the step to protect:

ElementWhat’s protectedExample
A button or linkIts click#continue-to-payment, a[href="/checkout/payment"]
A formIts submitform#payment-details

Protection keeps working when the element is re-rendered. In a single-page app, calling protect again with the same before updates its options.

3

Give the quote and the customer's mobile

quoteDetails returns this quote’s values as { quote, mobile }. It’s only called when the customer needs to approve (and on later presses after an approval, to detect a changed quote), so an ordinary check sends no personal data.

  • quote holds the product’s published fields, nested as their keys say. You’ll find them on the product’s Fields page in the portal. Dates are YYYY-MM-DD, money is { amount, currency } and lists are arrays. A missing required field or a value of the wrong type is refused; fields the product doesn’t define are dropped.
  • mobile is the customer’s own mobile number, where the approval code is sent.
  • Keep it fast and free of side effects. It’s called when a review starts, with up to 10 seconds to return. After an approval, it’s called each time the step is used, to check the quote hasn’t changed, and the step waits up to 2.5 seconds for it. Read the values already on your page rather than fetching them, and don’t change anything when it’s called.

The quote is what the customer sees and approves on the approval page, so check every value matches what they’ll pay for. See After an approval for how a changed quote is handled.

4

Add your own ID or signal (optional)

Two optional settings add context to each check:

HumanApproved.q.push(["protect", {
// …key, quote, before, quoteDetails as above
userId: "CUST-1001", // your own ID for this customer
signal: { source: "cloudflare", score: 2 }, // your own bot detection's result
}]);
  • userId is your own opaque ID for the customer, such as a customer or account number, so you can find their checks and approvals in the portal and your server gets it back with the review. Don’t use an email address, phone number or name. If the value looks like an email address or phone number, it isn’t stored.
  • signal passes the result of your own bot detection, for a product set to use your own signal on its Agent detection page. See Agent detection.

All options, including onResult for your own logging, are in protect() options.

5

Check what happens on the page

When someone uses the protected step, the embed holds the click or submit and asks HumanApproved whether to continue:

ResponseWhat happens
Continue (not an agent)Nothing visible. The original click or submit proceeds unchanged.
Review (an agent)The embed sends the quote and shows the agent a pause panel with a link to pass to the customer. It waits for the customer’s answer, and the wait resumes after a reload.
ApprovedThe panel closes and the step proceeds automatically.
Declined or expiredThe panel tells the agent nothing was paid, and to ask the customer what they want to do. The step stays paused, and the next try runs a new check.
No response in 2.5 seconds, or any errorThe step proceeds, and the browser console shows a warning with the reason.

You can change the panel’s wording and look on the product’s Agent popup page: see The pause panel. Whether the step pauses only for agents, for every purchase or never depends on the product’s When to ask for approval setting: see Approval methods.

6

Verify the approval on your server

The embed runs in the browser, and an agent driving the checkout controls that browser. Before you bind the policy, have your server confirm the approval with your secret key. See Verify on your server.

Next steps