Server Side Rendering — Cloudflare Setup Instructions

Modified on Fri, 7 Aug at 4:53 PM

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

  1. Install dependencies

   cd cloudflare-worker

   npm install
  1. 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"
  1. Optional: environment and highlighter cache
  • Data environment

    By default the Worker uses production (data.schemaapp.com). For test or UAT, set a variable in wrangler.toml under [vars]:

    • SCHEMA_DATA_ENV = "tst"datatst.schemaapp.com

    • SCHEMA_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

  1. Log in to Cloudflare (if needed)

   npx wrangler login
  1. 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

  1. In the Cloudflare dashboard, select the zone (domain) for your site.

  2. Go to Workers Routes (or Workers & PagesOverviewRoutes).

  3. 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 your wrangler.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-Type including text/html are 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_ID is 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_CACHE and 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)

  1. Set SCHEMA_ACCOUNT_ID in wrangler.toml [vars], or for local overrides use a .dev.vars file (do not commit):

   SCHEMA_ACCOUNT_ID=YourAccountId
  1. Start the Worker:

   npm run dev
  1. 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 --remote so the Worker runs in Cloudflare and receives real traffic (with a tunnel or test URL).

    • Stub origin: Use a tool like curl to 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).

  2. 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

  1. Deploy to a test Cloudflare zone (or a subdomain): npm run deploy.

  2. In the dashboard, add a Workers Route so the Worker runs on that zone (e.g. *test.example.com/*).

  3. Set SCHEMA_ACCOUNT_ID in wrangler.toml [vars] (or in the dashboard under Variables). For test data use SCHEMA_DATA_ENV = "tst" in Variables and a Schema App test account.

  4. Open a page on that host that has markup in the Schema App data cache (same URL logic as the JS embed: origin + pathname).

  5. 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.

  6. Optional: Run npm run tail and 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:

  1. 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).

  2. 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 run npm run tail (or npx wrangler tail) in the cloudflare-worker directory.

    • 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_DEBUG when you’re done (and redeploy) so you don’t fill logs.

  3. Confirm Schema App has markup for that URL

    • The Worker looks up markup by origin + pathname (e.g. https://yourdomain.com/ or https://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 (or npx wrangler tail) and load a page to see Worker logs and errors. Enable SCHEMA_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

Let us know how can we improve this article!

Select at least one of the reasons
CAPTCHA verification is required.

Feedback sent

We appreciate your effort and will try to fix the article