Schema App – Cloudflare Worker
Inject Schema App markup into your HTML at the edge using a Cloudflare Worker. The Worker fetches markup from Schema App’s data CDN (by page URL) and injects it as <script type="application/ld+json"> before </head>, so the browser never talks to Schema App directly.
Note: Currently Cloudflare Worker deployment is only available to Schema App Enterprise (Highlighter) customers.
Cloudflare Workers requirement (plan and cost) Schema App edge SSR on Cloudflare runs as a Cloudflare Worker attached to your site routes. This is separate from using Cloudflare for DNS, CDN, or WAF. • Workers are billed separately from your Cloudflare CDN plan (Free / Pro / Business). • Cloudflare includes a free Workers tier, but its daily request and CPU limits are generally not suitable for production site traffic. • Most production deployments need Workers Paid (or Cloudflare Enterprise Workers pricing). Confirm with your Cloudflare admin that Workers can be deployed and that usage cost is acceptable before go-live. • Being on Cloudflare does not mean Workers are already enabled or sized for this use case. See Cloudflare’s current Workers pricing for limits and rates (they can change).
You can download the package from the following link: https://cdn.schemaapp.com/javascript/schema-app-cloudflare-worker.tar.gz
tar -xzvf schema-app-cloudflare-worker.tar.gz
cd schema-app-cloudflare-worker
Background
This script is designed to fetch markup before it reaches the user’s browser so the markup is injected without the need for JavaScript support or rendering. It also means the markup is in the HTML source so even crawlers without support for JavaScript can see your Schema Markup. This functionality relies on markup already existing, so we recommend using the Crawler deployment on Highlighter templates. This will ensure markup is up to date and on the CDN without the need to run any scripts on your webpage. An added benefit is that since no scripts are run in user browsers, no user data is collected.
Prerequisites
Node.js (v20+ LTS recommended)
A Cloudflare account with permission to deploy Workers and attach Workers Routes
Your site (or a route) proxied through Cloudflare (orange-cloud / proxied DNS)
Workers Paid (or Cloudflare Enterprise Workers) recommended for production. Free Workers is fine for staging or low-volume tests only — see the callout above
Schema App Account ID from Schema App → Integration → JavaScript
Cached markup on Schema App’s data CDN for the URLs you will serve (typically via Crawler deployment on Highlighter templates)
Setup
- Install dependencies
cd cloudflare-worker
npm install
- Set your Schema App account ID
Edit wrangler.toml and set SCHEMA_ACCOUNT_ID in the [vars] section to your Schema App account ID (e.g. the path after schemaapp.com/db/):
[vars]
SCHEMA_ACCOUNT_ID = "YourAccountId"
- Optional: environment and highlighter cache
Data environment
By default the Worker uses production (
data.schemaapp.com). For test or UAT, set a variable inwrangler.tomlunder[vars]:SCHEMA_DATA_ENV = "tst"→datatst.schemaapp.comSCHEMA_DATA_ENV = "uat"→datauat.schemaapp.com
Highlighter cache
To also inject markup from the highlighter cache (aligned with “fetch from highlight JS cache” in the JS embed), set:
SCHEMA_FETCH_HIGHLIGHTER_CACHE = "true"in[vars]
Deploy
- Log in to Cloudflare (if needed)
npx wrangler login
- Deploy the Worker
npm run deploy
Or:
npx wrangler deploy
After deployment, Wrangler prints the Worker’s URL. The Worker does nothing until you attach it to a route.
Attach the Worker to your site
In the Cloudflare dashboard, select the zone (domain) for your site.
Go to Workers Routes (or Workers & Pages → Overview → Routes).
Add a route:
Route: e.g.
*example.com/*(all paths) or*example.com/blog/*(only under/blog).Worker: choose
schema-app-markup(or the name in yourwrangler.toml).
Once the route is active, HTML responses for that route will be processed by the Worker and schema markup will be injected when available for the requested URL.
Bot vs human traffic: Unlike Akamai’s common bot-only Property Manager setup, Cloudflare Workers run on whatever routes you attach. Human visitors may receive injected markup (and Worker invocations count toward usage) unless you add your own bot-only routing.
Behavior
URL for lookup: The Worker uses the request URL with query and fragment stripped (origin + pathname), matching the “strip URLs” behavior of the JavaScript embed.
HTML only: Only responses with
Content-Typeincludingtext/htmlare modified. Others are returned unchanged.Injection: Markup is inserted as
<script type="application/ld+json">…</script>immediately before</head>. If the Schema App data endpoint returns no markup or errors, the original HTML is returned unchanged.Missing config: If
SCHEMA_ACCOUNT_IDis not set (in[vars]or dashboard), the Worker forwards the request without injection.
Local development
npm run dev
Use the local URL Wrangler prints. For local testing you’ll need a way to hit your origin (e.g. --remote or a tunnel). Config is read from wrangler.toml; use .dev.vars for local overrides (do not commit .dev.vars).
Limitations
Request URL only: The Worker does not read
<link rel="canonical">from the page; it uses the request URL only.Cached markup only: This path injects markup that is already in the Schema App data cache. It does not run the highlighter or other client-side logic unless you enable
SCHEMA_FETCH_HIGHLIGHTER_CACHEand that markup exists in the cache.Workers plan limits: Free Workers request/CPU limits will typically block or throttle production traffic. Plan for Workers Paid or Enterprise before production cutover.
CDN alone is not enough: Cloudflare proxy/WAF without a deployed Worker and route will not inject Schema App markup.
Testing
Live test site (domain + Pages + Worker)
To test on a real website with no existing domain: use the minimal test-site and follow docs/LIVE-TEST-SETUP.md. That guide walks through getting a domain, adding it to Cloudflare, deploying the test-site with Cloudflare Pages, deploying the Worker, and attaching the Worker to your domain.
1. Unit tests (no deploy)
Run tests for URL normalization, base64 encoding, and HTML injection (no live fetch or Cloudflare):
cd cloudflare-worker
npm install
npm test
Requires Node 20+ (see engines in package.json). Tests live in src/index.test.ts.
2. Local dev (Worker + real origin)
- Set
SCHEMA_ACCOUNT_IDinwrangler.toml[vars], or for local overrides use a.dev.varsfile (do not commit):
SCHEMA_ACCOUNT_ID=YourAccountId
- Start the Worker:
npm run dev
The Worker runs locally but must receive requests that look like your real site. Options:
Same zone in Cloudflare: Use a route that points to a test hostname that proxies to your origin; in dev you can use
wrangler dev --remoteso the Worker runs in Cloudflare and receives real traffic (with a tunnel or test URL).Stub origin: Use a tool like
curlto send a request to the Worker URL with a Host header that matches a zone where the Worker is attached, and mock the “origin” by having the Worker fetch a known HTML URL (would require a small config change to pass an origin override for testing).
- Inspect the response: the HTML should contain
<script type="application/ld+json">before</head>when the data endpoint returns markup for that URL.
3. Deployed integration test
Deploy to a test Cloudflare zone (or a subdomain):
npm run deploy.In the dashboard, add a Workers Route so the Worker runs on that zone (e.g.
*test.example.com/*).Set SCHEMA_ACCOUNT_ID in
wrangler.toml[vars](or in the dashboard under Variables). For test data useSCHEMA_DATA_ENV = "tst"in Variables and a Schema App test account.Open a page on that host that has markup in the Schema App data cache (same URL logic as the JS embed: origin + pathname).
Verify: View source or Inspect; the
<head>should contain one or more<script type="application/ld+json">blocks. You can compare with the same URL using the JavaScript integration to confirm the same markup is injected.Optional: Run
npm run tailand load the page to see Worker logs and any errors.
Verifying the Worker is working
If the Worker appears in your invocation logs but you’re not sure it’s doing anything, use these checks:
View the response HTML
Open your page, then View Page Source (right‑click → View Page Source), or open DevTools → Network → select the document request → Response.
If the Worker is injecting and Schema App has markup for that URL, you’ll see one or more
<script type="application/ld+json">…</script>blocks inside<head>, right before</head>.If you see your normal HTML but no such scripts, the Worker is likely running but the Schema App data endpoint returned no markup for that URL (see step 3).
Use real-time logs with debug
Set a variable for the Worker:
SCHEMA_DEBUG=true(Workers & Pages → your Worker → Settings → Variables).Redeploy the Worker (
npm run deploy), then runnpm run tail(ornpx wrangler tail) in thecloudflare-workerdirectory.Load your page in the browser. In the tail output you should see one of:
[schema-app-worker] injected N script(s) for <url>— markup was found and injected.[schema-app-worker] no markup for URL (data endpoint returned none): <url>— Worker ran and asked Schema App, but there was no markup for that URL.[schema-app-worker] pass-through: ...— Worker ran but skipped (e.g. not HTML, or missing credentials).
Turn off
SCHEMA_DEBUGwhen you’re done (and redeploy) so you don’t fill logs.
Confirm Schema App has markup for that URL
The Worker looks up markup by origin + pathname (e.g.
https://yourdomain.com/orhttps://yourdomain.com/about). Query/fragment are stripped.In Schema App, ensure that URL has cached markup for your account. Quick check: put the JavaScript integration on a test page with the same URL and confirm JSON-LD appears there. If the JS embed shows no markup for that URL, the Worker will also have nothing to inject.
Troubleshooting
No markup on the page: Confirm the page URL (origin + pathname) has markup in Schema App for your account (e.g. test with the JavaScript integration on the same URL). Ensure the route is correct and the Worker is attached.
Worker errors / 1027 or quota issues: Check whether the account is on Free Workers and has hit daily request or CPU limits. Upgrade to Workers Paid (or Enterprise) for production traffic. See Workers pricing and Workers limits.
Logs: Run
npm run tail(ornpx wrangler tail) and load a page to see Worker logs and errors. EnableSCHEMA_DEBUG = true(see above) to see whether the Worker injected or passed through.
Building the customer package (maintainers)
To create a tar file for distribution to customers (e.g. for support or downloads), from the schema-scripts repo root or from cloudflare-worker:
cd cloudflare-worker
npm run pack:customer
This produces cloudflare-worker/dist/schema-app-cloudflare-worker.tar.gz. The archive contains everything needed to deploy (source, config, README, test-site, docs) and excludes node_modules, .wrangler, .dev.vars, and internal docs. Customers extract the archive, run npm install, set SCHEMA_ACCOUNT_ID in wrangler.toml, and deploy as described in this README.
Was this article helpful?
That’s Great!
Thank you for your feedback
Sorry! We couldn't be helpful
Thank you for your feedback
Feedback sent
We appreciate your effort and will try to fix the article