Skip to main content
The script (script.js) is a self-contained vanilla JavaScript file under 20KB. It runs as an IIFE (immediately invoked function expression) — it never pollutes the global scope and will never break your page.

Execution order

Every time the script loads on a page, it does the following in sequence:
1

Ping (immediate)

Before anything else, the script fires a POST to /api/ping with the current page URL and script version. This confirms the script is correctly installed — your dashboard installation badge updates within seconds.
2

Inject discoverability tags

The script adds machine-readable metadata to the page <head> so AI agents can find the manifest:
<meta name="webmcp" content="https://openhermit.com/api/manifest?key=YOUR_KEY" />
<link rel="webmcp" href="https://openhermit.com/api/manifest?key=YOUR_KEY" />
3

Detect AI agents

The script checks the user-agent string for known AI crawlers (GPTBot, ClaudeBot, PerplexityBot, Google-Extended, Operator, and others) and headless browser signals. If an agent is detected, it’s recorded with each event.
4

Scan for forms

All <form> elements on the page are scanned. For each form, the script:
  • Extracts all input fields (name, type, required, placeholder)
  • Classifies the form type: contact_form, booking, newsletter, signup, purchase, quote, login, search, upload, or support
  • Generates a human-readable name from aria-labels, legends, nearby headings, or the form ID
  • Generates a tool_name (snake_case, used in the manifest)
  • Injects data-mcp-action, data-mcp-description, data-mcp-params attributes
5

Detect third-party widgets

The script detects embedded widgets that aren’t standard HTML forms:
WidgetDetection method
Calendlywindow.Calendly object or .calendly-inline-widget
Typeformtf-widget element or typeform embed script
HubSpotwindow.hbspt or .hs-form
Intercomwindow.Intercom
Driftwindow.drift
Crispwindow.$crisp
6

Extract business info

The script reads Schema.org JSON-LD from the page (@type: LocalBusiness, Organization, etc.) to extract the business name, description, address, and phone number. This enriches the manifest.
7

Sync to OpenHermit

All detected actions (and business info) are sent to /api/actions/sync. OpenHermit stores new actions or updates existing ones — preserving any agent prompts you’ve already configured. The API returns your configured prompts back.
8

Inject agent prompts into DOM

Any configured prompts are injected as a hidden off-screen div with an aria-label. This means both DOM-reading and accessibility-tree-reading agents can find your instructions without any visual impact on the page.
9

Track form submissions

Event listeners are added to form submit buttons. When a form is submitted, a completion or error event is sent to /api/events via navigator.sendBeacon (fire-and-forget — never slows down the page).
10

Watch for dynamic content (SPAs)

A MutationObserver watches for new content added to the DOM. If a form appears after the initial load (common in React/Vue/Angular apps), the script re-runs detection automatically.

Form type detection

The script classifies forms by scanning their HTML for keyword signals:
TypeSignals
contact_formcontact, message, inquiry, reach out, get in touch
bookingbook, appointment, schedule, reserve, calendar, slot
newsletternewsletter, subscribe, email list, updates, notify
signupsign up, register, create account, join, membership
purchasebuy, checkout, order, purchase, payment, cart
quotequote, estimate, calculate, price, cost, proposal
loginlogin, sign in, password, username
searchsearch, find, look for
uploadupload, attach, file, CV, resume, document
supportsupport, help, ticket, issue, problem, complaint
If no signal matches, the form is classified as contact_form by default.

Performance impact

  • Script size: < 20KB uncompressed
  • Loads async — never blocks page rendering
  • Uses sendBeacon for event tracking — fire-and-forget, zero latency impact
  • Only runs after DOMContentLoaded — doesn’t affect Time to First Byte or FCP

Security

The script never reads or transmits form field values. It only reads:
  • Field names, types, and labels (for schema building)
  • Page URL and title
  • User agent string (for agent detection)
  • Schema.org structured data (if present)
Sensitive user input is never captured.