Web Widgets

Web Widgets

One loader script adds OnePath's widgets, the booking scheduler and the text-me-back chat form, to your site.

<head>
  <script src="https://cdn.onepath.ai/loader.js"></script>
</head>
<body>
  <button data-onepath-web-scheduler-trigger>Book a service</button>
  <button data-onepath-web-chat-trigger>Text me back</button>
</body>

Put the script in the document head. Add a button anywhere. That is the whole integration: no token, no per-widget scripts, no init call. The loader picks up every widget enabled on the account.

Your domain must be on the account's Allowed websites list

The loader recognizes the account from the domain the page is served on. If that domain (including your staging domain) is not on the list, the widget never renders and the button does nothing. Add it under Account settings → Lead Capture → Channels → Web Widgets card → Allowed websites, or ask whoever manages the account. Channels

Using a speed plugin? Safelist cdn.onepath.ai

If your site runs a performance plugin that delays, defers or combines JavaScript, such as NitroPack, WP Rocket, LiteSpeed Cache, Perfmatters, Flying Scripts or Cloudflare Rocket Loader, safelist the whole cdn.onepath.ai domain in it. In NitroPack that is Excluded Resources → Delayed Scripts; other plugins name the setting similarly.

Safelisting the loader tag alone is not enough. loader.js is only the starting point: while your page loads it fetches the rest of the widget, the scheduler, the chat and their shared runtime, as separate scripts from that same domain. Those are the ones these plugins rewrite or hold back.

When that happens the page looks completely normal and the button appears, but clicking it does nothing, because the scripts behind it never ran. Safelisting the domain covers the loader and everything it fetches.

How the account is recognized

There is no key in the snippet. The loader sends the page's address to OnePath, and OnePath looks up which account lists that domain.

  • The domain must be on the account's Allowed websites list (Account settings → Lead Capture → Channels → Web Widgets card → Allowed websites).
  • The business website entered under Business Info is always on the list and cannot be removed.
  • A root domain entry (acme.com or www.acme.com) covers every subdomain, such as staging.acme.com or book.acme.com. A subdomain entry covers only that subdomain.
  • The Web Widgets toggle on the Channels page must be on. Turning it off disables the scheduler and chat on every site at once.

When the domain is not recognized, the loader's request to https://app.onepath.ai/api/public/authentication answers 403 and nothing else loads. That request is the first thing to check in dev tools. See Troubleshooting.

Rules for the script tag

  • Exactly one loader tag per page. If a plugin or tag manager already adds it, do not add it again in the theme.
  • Do not add an integrity attribute (SRI). loader.js is updated continuously, so a pinned hash breaks the embed at the next release.
  • Keep it in the head. The loader works from anywhere on the page, but an onepath:webscheduler:open event dispatched before loader.js has run is lost. Trigger clicks are safe wherever the tag sits: a click that happens before the widget is ready is replayed once it is.
  • Leave it as a plain <script src> tag. No attributes are read from it.

What the loader loads

  1. It fetches the account's public configuration (name, colors, logo, phone, which widgets are enabled) and fires onepath:config-ready.
  2. It loads the scripts for the enabled widgets from cdn.onepath.ai. Those scripts are versioned, so there is nothing to cache-bust; new releases reach your site within about five minutes.
  3. If a visitor clicked a trigger while the widgets were still loading, that click is replayed.

Nothing is visible on page load. The scheduler is a modal that opens from a trigger. Chat is a panel that opens from its trigger; no floating bubble is rendered, your site supplies the button. A third, invisible module registers booking tools for AI agents in Chrome; see Booking by AI agents. Both widgets render in isolated styles, so your CSS does not leak into them. Colors and logo come from the account, not from the tag. See What your visitors see.

Buttons, context, and pre-selection

Any element with data-onepath-web-scheduler-trigger opens the scheduler. Add data-onepath-context, data-onepath-serviceable-type and data-onepath-service-type to attach a package to the booking and pre-select the service:

<div data-onepath-context
     data-onepath-serviceable-type="Water Heater"
     data-onepath-service-type="Estimate">
  Better Package — 50 Gallon — $2,695
  <button data-onepath-web-scheduler-trigger>Book this package</button>
</div>

→ Every option, URL parameters, and what the context looks like downstream: Buttons, links & context

Open the scheduler from your own form

Dispatch one event with the visitor's details and the scheduler opens pre-filled.

→ Open the scheduler from a form submit

Chat widget

The same loader serves the chat form. It is a short "we'll text you" form, not live chat.

→ Chat widget

Next steps

PageWhat it covers
Add the widgets to your siteWordPress, Webflow, Squarespace, Wix, Google Tag Manager, React/Next.js, and how to verify
What your visitors seeThe booking flow screen by screen and the setting behind each part
Booking by AI agentsChrome WebMCP tools that let an AI assistant book without the form
EventsBooking events for GA4, Tag Manager, and redirects
Webhook eventsServer-side JSON POST for appointment changes, calls that need attention, and hand-offs to your team
TroubleshootingSymptom → cause → fix
Legacy Web Scheduler embedMigrating from onepath-embed.js
Previous
Integrations