Not every site can run a Cloudflare Worker or modify server templates. The Legible JavaScript discovery snippet gives you a one-line install that injects AI-discovery tags client-side — on any platform, any CMS, any hosting provider.
This guide explains how to add the snippet, what it does under the hood, its limitations with non-JS crawlers, and how to combine it with manual HTML tags for full coverage.
Quick start
Add one script tag to your site's <head>. That is the entire installation. The snippet fetches your site's discovery configuration from Legible's API and injects the correct <link> and <meta> tags into the page.
- Replace YOUR_SITE_ID with the Site ID from your Legible dashboard (Settings → Discovery tab).
- The async attribute ensures the snippet never blocks page rendering.
- In Webflow, paste it into Project Settings → Custom Code → Head Code.
- In Squarespace, go to Settings → Advanced → Code Injection → Header.
- In Shopify, edit your theme's theme.liquid file and add it inside <head>.
- In WordPress, the Legible plugin handles this automatically — you do not need the snippet.
<script src="https://getlegible.com/js/discover.js"
data-site="YOUR_SITE_ID" async></script>What the snippet does
When the page loads, the snippet runs through a simple sequence. It reads your Site ID from the data-site attribute, fetches a lightweight JSON config from the Legible public API, and creates DOM elements for each discovery tag. Before injecting, it checks whether the tag already exists in the page — so it plays nicely with manually added tags or server-rendered tags from a plugin.
- Fetches GET /api/public/discovery-config?siteId=... (cached for 1 hour by CDN).
- Injects global tags on every page: <link rel="ai-index">, <meta name="legible:ai-content-base">, <meta name="legible:ai-sitemap">.
- On content pages matching your collection path, injects a per-page <link rel="alternate" type="text/markdown"> with the correct slug.
- Skips any tag that already exists in <head> (deduplication).
- Optionally sends a lightweight analytics beacon via navigator.sendBeacon (respects Do Not Track).
Limitations
The most important limitation is that most AI crawlers do not execute JavaScript. GPTBot, ClaudeBot, CCBot, and most others parse the raw HTML source and never run scripts. Tags injected by the snippet will be invisible to these crawlers.
This means the snippet alone does not provide full AI discoverability. It is best used as a supplement — either alongside server-rendered tags, or as a quick-start that you upgrade to server-side injection later.
- AI crawlers (GPTBot, ClaudeBot, CCBot, Perplexity) — will NOT see JS-injected tags.
- Googlebot — will see them (Googlebot renders JavaScript).
- Legible's GEO Readiness audit — will see them (uses a headless browser).
- Human visitors and browser extensions — will see them.
- For full AI crawler coverage, use Cloudflare proxy mode or add the tags directly to your HTML templates.
Combining the snippet with manual HTML tags
The recommended setup for proxy-free sites is to add the server-rendered HTML tags manually and use the snippet as a safety net. The snippet's deduplication logic ensures tags are never doubled.
You can find the exact HTML tags to copy in your Legible dashboard under Settings → Discovery → Manual HTML tags. They look like this:
<!-- Global tags (add to your site's <head>) -->
<link rel="ai-index" type="text/plain"
href="https://read.yoursite.com/llms.txt" />
<meta name="legible:ai-content-base"
content="https://read.yoursite.com/" />
<meta name="legible:ai-sitemap"
content="https://read.yoursite.com/ai-sitemap.json" />
<!-- Per-page tag (add to content templates) -->
<link rel="alternate" type="text/markdown"
href="https://read.yoursite.com/blog/{{slug}}.md" />
<!-- Plus the snippet for analytics and fallback -->
<script src="https://getlegible.com/js/discover.js"
data-site="YOUR_SITE_ID" async></script>Snippet attributes reference
- data-site (required) — Your Legible Site ID. Found in Settings → Discovery.
- data-api (optional) — Override the API base URL. Defaults to https://getlegible.com. Useful for self-hosted or staging setups.
- data-no-analytics="true" (optional) — Disable the analytics beacon entirely. The beacon is already suppressed when Do Not Track is enabled.
- async (recommended) — Load the script without blocking page rendering. Always include this attribute.
Analytics beacon
By default, the snippet sends a small analytics beacon on each page view using navigator.sendBeacon. This is non-blocking and does not slow down the page. The beacon contains only the page path, referrer, and a timestamp — no cookies, no fingerprinting, no personal data.
The beacon respects the browser's Do Not Track setting. If DNT is enabled, no beacon is sent. You can also disable it entirely with the data-no-analytics attribute.
Troubleshooting
- Tags not appearing: Open your browser's DevTools → Elements → search for "data-legible". Tags injected by the snippet have a data-legible="1" attribute. If they are missing, check the Console for errors.
- Config fetch fails: Verify your Site ID is correct. Open https://getlegible.com/api/public/discovery-config?siteId=YOUR_SITE_ID directly in a browser to check the response.
- Tags duplicated: This should not happen — the snippet checks for existing tags before injecting. If you see duplicates, check whether another script or plugin is also injecting tags.
- GEO score not updating: Run a fresh GEO Readiness audit from the Legible dashboard. The audit uses a headless browser that will see JS-injected tags, but cached results may be stale.
Privacy and performance
The snippet is designed to be lightweight and privacy-respecting. The script itself is under 2 KB. The config fetch is cached by the CDN for one hour, so repeat visitors rarely trigger a network request. No cookies are set, no localStorage is used, and no personal data is collected.
The analytics beacon is opt-in by nature — it only fires if the browser supports sendBeacon, and it respects Do Not Track. The data is used solely for page-view counts in your Legible analytics dashboard.
