Cloudflare Worker Integration
Sophi Paywall with MonetizationOS (MOS) is deployed via the officially maintained Cloudflare Proxy Worker — an open-source reference implementation of the MonetizationOS proxy , built on Cloudflare Workers . It is a ready-to-deploy Worker, not a library you build a Worker around — integration is configuration, not custom code.
View the Cloudflare Proxy Worker on GitHub — that page also has a “Deploy to Cloudflare” button for a one-click deploy.
This page is the client-facing setup and rollout guide. For the authoritative implementation reference — the full environment variable list, request pipeline, HTML transformation, and error handling — see the MonetizationOS docs linked throughout; this page links to the relevant section rather than duplicating it.
1. How it works
The Worker sits on the site’s hostname, fetches from the origin, and calls the MonetizationOS Surface Decision API for every HTML response. See the request pipeline for the full stage-by-stage flow (custom endpoint routing → origin fetch → link rewriting → identity resolution → Surface Decision API call → surface behavior → component behaviors).
Any failure after the origin fetch is caught and the Worker fails open — the visitor still gets the origin response. See Error handling .
2. Prerequisites
| Item | Who provides it |
|---|---|
| Cloudflare account with Workers enabled, on the zone that serves the site | Client |
Wrangler CLI (npm i -D wrangler) | Client |
MONETIZATION_OS_SECRET_KEY (secret key from the MonetizationOS dashboard) | MonetizationOS |
SURFACE_SLUG for each surface (e.g. web) | MonetizationOS |
Origin hostname the Worker should proxy to (ORIGIN_URL) | Client |
| Cookie names used for sessions — authenticated JWT and anonymous session | Client |
Decision: which paths skip Surface Decisions (SURFACE_DECISIONS_IGNORE_PATHS) | Client + MonetizationOS |
3. Worker configuration
All settings are Cloudflare Worker bindings ,
set in wrangler.jsonc for deployed environments or a .dev.vars.local file for local
development. The full variable reference — including optional variables and their defaults —
lives in
Environment variables .
The variables every integration must set:
| Variable | Description |
|---|---|
MONETIZATION_OS_SECRET_KEY | Secret key from the MonetizationOS dashboard. Also derives the environment prefix for custom endpoint routing . |
ORIGIN_URL | Base URL of the client origin. All non-endpoint requests are proxied here. |
SURFACE_SLUG | The MonetizationOS surface to evaluate for every HTML request. |
AUTHENTICATED_USER_JWT_COOKIE_NAME | Cookie name containing the authenticated user’s JWT. |
ANONYMOUS_SESSION_COOKIE_NAME | Cookie name for anonymous session identifiers. |
Example wrangler.jsonc for a production deployment:
{
"name": "mos-proxy",
"main": "src/index.ts",
"compatibility_date": "2026-08-01",
"routes": [
{ "pattern": "www.client.com/*", "zone_name": "client.com" }
],
"vars": {
"ORIGIN_URL": "https://origin.client.com",
"SURFACE_SLUG": "web",
"AUTHENTICATED_USER_JWT_COOKIE_NAME": "__session",
"ANONYMOUS_SESSION_COOKIE_NAME": "anon-session-id"
}
}MONETIZATION_OS_SECRET_KEY is a secret, not a plain var — set it per environment with:
npx wrangler secret put MONETIZATION_OS_SECRET_KEYFor local development, put the equivalent values in a git-ignored .dev.vars.local:
MONETIZATION_OS_SECRET_KEY=sk_test_...
ORIGIN_URL=https://origin.client.com
SURFACE_SLUG=web
AUTHENTICATED_USER_JWT_COOKIE_NAME=__session
ANONYMOUS_SESSION_COOKIE_NAME=anon-session-idA few optional variables worth deciding on up front:
| Variable | Default | Purpose |
|---|---|---|
MONETIZATION_OS_HOST | https://api.monetizationos.com | Override the MonetizationOS API host. |
MONETIZATION_OS_ENDPOINTS_PREFIX | /mos-endpoints/ | URL prefix routed directly to MOS as Endpoint Workflow requests. |
INJECT_SCRIPT_URL | unset | If set, injects <script src="{INJECT_SCRIPT_URL}" async defer></script> into <head> on every HTML response. |
SURFACE_DECISIONS_IGNORE_PATHS | unset | Comma-separated regex patterns for paths that should skip Surface Decisions entirely (e.g. /api/, static assets). |
No client-written HTML rewriting, identity resolution, or Surface Decision API call code is needed — the Worker already implements all of it. See HTML transformation with HTMLRewriter and Identity resolution for how those stages behave.
If a client needs a provider MonetizationOS doesn’t ship a reference Worker for, see Custom Proxy Integration , which documents the underlying runtime-agnostic
@monetizationos/proxycore that this Worker — and the Fastly and Akamai reference implementations — are built on.
4. Cloudflare request context
The Worker automatically forwards request.cf — Cloudflare’s
incoming request properties
(geolocation, device, network, bot signals) — to the Surface Decision API on every call. No
configuration is required to enable this; Surface Workflows can use it directly for targeting.
See Cloudflare request context .
5. Routing traffic to the Worker
Two options — pick one with the client:
| Option | How | When |
|---|---|---|
| A. Worker on the public hostname (recommended) | Add a Worker route for www.client.com/* on the existing zone; DNS for www becomes a proxied (orange-cloud) record — since the route intercepts before DNS resolution. | The site is already on Cloudflare (or can be onboarded). |
| B. Workers subdomain / gradual | Serve from *.workers.dev or a staging hostname first; cut over by changing DNS when validated. | The site is not on Cloudflare yet, or a staged migration is required. |
Origin protection is required once the Worker fronts the site, otherwise visitors (and scrapers) can bypass the paywall by hitting the origin directly. Options, best first:
- Authenticated Origin Pulls (mTLS) — Cloudflare presents a client certificate; origin rejects anything else.
- Secret header — the origin only accepts requests carrying a header only the Worker sends; reject everything else.
- IP allow-list — origin firewall allows only Cloudflare IP ranges (weakest of the three; headers are easier to verify).
6. Cookie & identity considerations
Identity is resolved from cookies before the Surface Decision API is called — see Identity resolution . The client must confirm:
AUTHENTICATED_USER_JWT_COOKIE_NAMEandANONYMOUS_SESSION_COOKIE_NAMEmatch what the site actually sets (e.g. Auth0/Clerk/custom auth often use__session,appSession, etc.).- Cookies are set on the parent domain (
.client.com) if subdomains must share identity. - If neither cookie is present, the Worker generates a new anonymous session ID and sets it via
Set-Cookie— confirm this is acceptable for the client’s cookie/consent policy.
7. Verification & rollout
- Local:
npx wrangler dev→ browse pages; expect the anonymous-session cookie to appear. - Staging: point a staging hostname at the Worker (Option B above), run the paywall scenarios (anonymous metered, subscribed user, bot UA, non-HTML assets, POST forms).
- Observability: the Worker logs to
console.erroron failure — wire Workers Logpush / dashboard alerts on any error-level log. - Cutover: enable the route on the production hostname; monitor origin bypass attempts, error rate, and added latency (the Surface Decision API call is the dominant added latency — once per uncached HTML page view).
- Rollback: remove the Worker route — traffic flows directly to the origin again.
8. Failure modes the client should know
| Failure | Behavior |
|---|---|
| Surface Decision API down/timeout | Caught by the Worker’s error handling; original origin response returned unmodified. Fail-open. |
| Non-HTML content | Always passes through unchanged. |
| Origin down | Origin’s error response passes through (the Worker does not mask origin failures). |
See Error handling for the exact behavior.
9. Client questionnaire
The open questions for the client development team live on a standalone page: the readiness questionnaire. Send it before implementation starts — every answer maps to a configuration value in §3.
10. Deliverables checklist
- Worker deployed from the Cloudflare Proxy Worker repo , configured per §3
- Secrets configured in Cloudflare (per environment)
- Origin bypass protection enabled
- Staging hostname verified against the full scenario matrix
- Log alerts wired
- Runbook: how to disable the route (rollback) and how to rotate
MONETIZATION_OS_SECRET_KEY