Cloudflare Worker Setup
The Cloudflare Worker integration is the recommended way to set up Server-Side Tracking. It runs at the edge on Cloudflare's network, capturing every request before it reaches your origin server — including cached responses.
Prerequisites
- A website proxied through Cloudflare (orange cloud enabled)
- A Travatar account with an App ID and API Token
- Access to Cloudflare Dashboard → Workers & Pages
Setup Steps
1. Get Your Credentials
- Log in to app.travatar.ai
- Go to Settings → Server Tracking
- Copy your App ID and generate an API Token (save it — it's shown only once)
2. Create the Worker
- Go to Cloudflare Dashboard → Workers & Pages
- Click Create Worker
- Name it
travatar-sst(or any name you prefer) - Replace the default code with the following:
const WEBHOOK_URL = "https://log-tracker.travatar.ai/webhook";
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
const metadata = {
timestamp: new Date().toISOString(),
app_id: env.TRAVATAR_APP_ID,
// Request info
method: request.method,
url: request.url,
path: url.pathname,
query: url.search,
host: url.hostname,
origin: url.origin,
// All headers
headers: Object.fromEntries(request.headers),
// Referral & navigation
referer: request.headers.get("referer"),
origin_header: request.headers.get("origin"),
// Client identification
user_agent: request.headers.get("user-agent"),
accept_language: request.headers.get("accept-language"),
accept: request.headers.get("accept"),
// Client IP
client_ip: request.headers.get("cf-connecting-ip"),
x_forwarded_for: request.headers.get("x-forwarded-for"),
// Cloudflare headers
cf_ipcountry: request.headers.get("cf-ipcountry"),
cf_ray: request.headers.get("cf-ray"),
cf_visitor: request.headers.get("cf-visitor"),
// Cloudflare request properties (geo, network, bot detection, TLS)
cf: request.cf
? {
country: request.cf.country,
city: request.cf.city,
continent: request.cf.continent,
region: request.cf.region,
regionCode: request.cf.regionCode,
latitude: request.cf.latitude,
longitude: request.cf.longitude,
postalCode: request.cf.postalCode,
timezone: request.cf.timezone,
isEUCountry: request.cf.isEUCountry,
asn: request.cf.asn,
asOrganization: request.cf.asOrganization,
colo: request.cf.colo,
tlsVersion: request.cf.tlsVersion,
httpProtocol: request.cf.httpProtocol,
botManagement: request.cf.botManagement,
}
: null,
// Security hints
sec_ch_ua: request.headers.get("sec-ch-ua"),
sec_ch_ua_mobile: request.headers.get("sec-ch-ua-mobile"),
sec_ch_ua_platform: request.headers.get("sec-ch-ua-platform"),
sec_fetch_dest: request.headers.get("sec-fetch-dest"),
sec_fetch_mode: request.headers.get("sec-fetch-mode"),
sec_fetch_site: request.headers.get("sec-fetch-site"),
dnt: request.headers.get("dnt"),
};
// Send metadata to Travatar (non-blocking)
ctx.waitUntil(
fetch(WEBHOOK_URL, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-TRAVATAR-SST-TOKEN": env.TRAVATAR_SST_TOKEN,
"X-TRAVATAR-SST-SOURCE": "cf_worker",
},
body: JSON.stringify(metadata),
})
.then((res) => {
if (!res.ok) {
console.error(`Webhook error: ${res.status} ${res.statusText}`);
}
})
.catch((err) => {
console.error(`Webhook failed: ${err.message}`);
})
);
// Forward the original request to origin
const response = await fetch(request);
return response;
},
};
- Click Deploy
3. Add Environment Variables
- In the Worker settings, go to Settings → Variables
- Add two environment variables:
| Variable | Value |
|---|---|
TRAVATAR_APP_ID | Your App ID from Settings → Server Tracking |
TRAVATAR_SST_TOKEN | Your API Token from Settings → Server Tracking |
- Click Encrypt for
TRAVATAR_SST_TOKENto keep it secure - Click Save
4. Add a Route
- Go to your domain in Cloudflare → Workers Routes
- Click Add Route
- Configure:
- Route:
yourdomain.com/* - Worker:
travatar-sst
- Route:
- Click Save
5. Verify
- Visit your website in a browser
- Go to app.travatar.ai → AI Traffic or Non-Human Traffic
- You should see your visit appear within 1-2 minutes
How It Works
Visitor → Cloudflare Edge → Worker
├── Forward to origin → Response to visitor
└── POST to Travatar (non-blocking, fire-and-forget)
The Worker intercepts every request at the Cloudflare edge:
- It passes the request through to your origin server normally
- In parallel, it sends request metadata to Travatar
- The visitor receives the response with zero added latency
Cloudflare-Specific Data
The Cloudflare Worker captures rich data not available from other integrations:
- Geo — country, city, region, coordinates, timezone, EU status
- Network — ASN, organization, Cloudflare colo (data center)
- Bot detection — Cloudflare Bot Management scores (if enabled on your plan)
- TLS — version, cipher, protocol
- Client hints —
sec-ch-ua, platform, mobile detection
Filtering Requests
You can modify the Worker to skip static assets and reduce invocations:
// Skip static assets
const skip = ["/favicon.ico", "/_next/", "/static/", ".css", ".js", ".png", ".jpg", ".svg", ".woff"];
if (skip.some((s) => url.pathname.startsWith(s) || url.pathname.endsWith(s))) {
return fetch(request);
}
Place this at the beginning of the fetch function, right after const url = new URL(request.url).
Troubleshooting
No data in dashboard
- Check that the Worker route matches your domain (
yourdomain.com/*) - Verify environment variables are set correctly
- Check Worker logs in Cloudflare Dashboard → Workers → your worker → Logs
Worker errors in logs
Webhook error: 401— Check thatTRAVATAR_SST_TOKENmatches the token from Settings → Server TrackingWebhook error: 404— Check thatTRAVATAR_APP_IDmatches your App ID exactlyWebhook failed: ...— The Travatar endpoint may be temporarily unreachable. Events are fire-and-forget, so this is harmless.
High Worker invocations
The Worker runs on every request, including static assets. If you want to reduce invocations, add path filtering (see above). Cloudflare's free plan includes 100,000 requests/day.