Documentation · The embed script
Documentation
The embed script
One tag, a module the browser loads directly, and a read-first request cycle. This page states what it puts on your page as well as what it takes off it.
One tag, no inline code#
The pasted line is the module’s <script src> tag — the browser loads and runs the module directly, nothing is inlined into your page, and there is no separate loader that fetches a second file:
<script async src="https://seogence.com/seogence.js?host={hostname}&propertyId={propertyId}&token={capabilityToken}"></script>A domain with no Property ID gets key={domainKey} instead; domain and key are still accepted as aliases. The hostname is written into the tag when the line is generated, not read from the page at run time, and the request is authorised on that hostname, the identifier and the capability token together.
Because a plain script tag sends no Origin header, none is required to fetch the module file itself — so the module will be served to anyone holding a copy of your line, on any domain. What stays scoped is every request the module then makes; see Scope and removal below. If your site sends a Content-Security-Policy, it needs to allow our origin in script-src to load the module and in connect-src for the requests it makes afterward.
What it reads#
On a page it is allowed to capture, it reads:
- The page title and the meta description.
- The text and the raw HTML of the main content region — up to 500,000 characters of markup. The region is the first of
main,article,#content,.contentor[role="main"]; when a page has none of those, it falls back todocument.body.
It reads this only to compute a small change-detection hash locally, so it does not re-trigger work for a page that has not changed. Since the server now renders the page itself (see What it sends), none of this text or HTML leaves your site — the request carries only the page URL. It does not read cookies and does not capture what a visitor types. Pages are skipped when they carry noindex or sit under a private path prefix such as /cart, /checkout, /account, /login or /dashboard.
Capture waits for the load event plus a short settle delay, so it never delays what a visitor sees — and a visitor who leaves within about two seconds is not captured at all.
What it renders on your page#
The snippet is not invisible. Besides the JSON-LD it delivers, it can render third-party UI on your site:
- A branded Seogence badge overlay, on by default.
- A floating “Copy as Markdown” button, when the copy-for-AI button is switched on and Markdown delivery is enabled for the domain.
- An on-page topic directory, when the keyword component is enabled.
- All three are switchable from the install screen, and switching them off does not stop your index being served — that is a separate setting.
- A
<link rel="alternate" type="text/markdown">tag pointing at the page’s Markdown copy.
One collision to know about: the module adopts and overwrites any existing JSON-LD script on the page carrying data-auto-schema="true", and removes it on teardown. Do not use that attribute for your own structured data.
What it sends#
The request cycle is read-first, and that shapes what you will observe:
GET /api/schemafor the current URL. If a stored schema exists, it is injected and the cycle ends — nothing is generated. When the visit came from another site, the first read of the page load also carries that site’s host name, never the full address, so Seogence can count visits that arrive from an AI assistant.- Only when that returns
404/SCHEMA_NOT_FOUNDdoes the modulePOST /api/generate-schemawith just the page URL and identifiers — a trigger. Seogence then renders the page on its own infrastructure and generates schema from what it sees; your page’s text and HTML are never sent.
A generation call returns one of these outcomes:
CACHE_HIT— a fresh generation is already stored for this URL; nothing is re-rendered.GENERATED— the server rendered the page and produced a fresh schema.GENERATION_IN_PROGRESS— another request holds the claim for this URL. The response carriesretryAfterMsand no schema.THIN_CONTENT— the server’s render came back essentially empty (a parked page or an app shell that did not hydrate); nothing is stored and the module stops until the next navigation.
Because the module short-circuits on the stored-schema read, editing a page does not by itself trigger a new generation through the embed — schema.org output explains what does.
The module also re-runs on SPA navigation and on significant DOM changes, and retries a bounded number of times on GENERATION_IN_PROGRESS or a transient error.
Scope and removal#
- Every request the module makes after it loads is authorised against the URL it is actually running on, so on a hostname the capability token was not issued for, nothing is read, generated or injected. The module file itself is still served on request — pasted on another site it loads and renders the badge, and stops there.
- Delete the line and it stops immediately — nothing to cancel, nothing left behind.
Checked against Seogence v3.19.37 on . Every claim on these pages is tied to the code that makes it true, and our build re-checks them whenever that code changes.