Last active
October 24, 2023 19:00
-
-
Save mountainash/94cc7bb56d6702e6d127c340e75c1419 to your computer and use it in GitHub Desktop.
Aptabase website tracking using Cloudflare Zaraz
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* | |
> This Cloudfare Workers script takes a request from Zaraz | |
Use the Zaraz **HTTP Request Tool** with an endpoint set to the Worker URL running this script, with a trigger of **Pageview**, using the **POST JSON** method, with **Send all System and Client data** checked for each **pageView** and sends it to Aptabase's **HTTP API**. | |
Notes: | |
- Create an Environment Variable called `APATABASE_KEY` and set it to your API Key | |
- The endpoint is set to Europe, change to USA or self-hosted as needed | |
- toggle `isDebug` to `false` when you're ready to go live | |
**/ | |
export default { | |
async fetch(request, env) { | |
// Get JSON sent to the body of this request | |
const readRequestBody = async (request) => await request.json(); | |
// Extra the HREF, userAgent, bot score, and ip, city, region and country from the JSON payload | |
const getSelectedData = (reqBody) => { | |
const { | |
page, | |
device | |
} = reqBody; | |
return { | |
domain: page.url?.hostname, | |
path: page.url?.pathname, | |
userAgent: device.userAgent?.ua, | |
language: device.language, | |
ip: device.ip, | |
botScore: String(device.bot?.score), | |
location: `${device.location?.city}, ${device.location?.region}, ${device.location?.country}`, | |
}; | |
}; | |
const aptabaseDataFormat = (data) => { | |
const now = new Date(); | |
const isoString = now.toISOString(); // eg 2023-10-23T15:16:47.366Z, | |
return { | |
timestamp: isoString, | |
sessionId: data.ip, | |
eventName: 'page_view', | |
systemProps: { | |
locale: data.language, | |
isDebug: true, | |
appVersion: '1.0.0', | |
sdkVersion: 'aptabase-web@fake' | |
}, | |
props: JSON.stringify(data), | |
} | |
}; | |
// Send the data to Aptabase's HTTP API | |
const sendData = async (data, env) => { | |
const url = 'https://eu.aptabase.com/api/v0/event'; | |
const headers = { | |
'Content-Type': 'application/json', | |
'App-Key': env.APATABASE_KEY, | |
}; | |
return await fetch(url, { | |
method: 'POST', | |
headers: headers, | |
body: JSON.stringify(data), | |
}); | |
} | |
if (request.method === 'POST') { | |
const reqBody = await readRequestBody(request); | |
// console.info(reqBody); | |
const selectData = getSelectedData(reqBody); | |
// console.info(selectData); | |
const aptabaseData = aptabaseDataFormat(selectData); | |
// console.info(aptabaseData); | |
const response = await sendData(aptabaseData, env); | |
if (!response.ok) | |
console.error(response); | |
return new Response('✅'); | |
} else if (request.method === 'GET') { | |
return new Response('The request was a GET. Needs to be a POST.'); | |
} | |
}, | |
}; |
NOTE: this script, as-is is using IP address for session IP - which is not ideal (long-lived, may not be unique per user/session) and could have PII implications. Please change #L42 to sessionId: Math.floor(Math.random() * 100000000)
[or similar] but it's likely all your sessions will be unique and unlinked for each hit. It depends on your expected use-case.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Linked from aptabase/aptabase#13