UNPKG

netlify-cli

Version:

Netlify command line tool

117 lines (99 loc) 4.06 kB
// with thanks to https://github.com/codeniko/simple-tracker/blob/master/examples/server-examples/aws-lambda/google-analytics.js const querystring = require('querystring') const fetch = require('node-fetch') const { v4: uuidv4 } = require('uuid') const GA_ENDPOINT = `https://www.google-analytics.com/collect` const whitelistDomain = function (domain, addWww = true) { const prefixes = ['https://', 'http://'] if (addWww) { prefixes.push('https://www.') prefixes.push('http://www.') } prefixes.forEach((prefix) => { originWhitelist.push(prefix + domain) }) } // Domains to whitelist. Replace with your own! // keep this empty and append domains to whitelist using whiteListDomain() const originWhitelist = [] whitelistDomain('test.com') whitelistDomain('nfeld.com') const proxyToGoogleAnalytics = async function (event) { // get GA params whether GET or POST request const params = event.httpMethod.toUpperCase() === 'GET' ? event.queryStringParameters : JSON.parse(event.body) const headers = event.headers || {} // attach other GA params, required for IP address since client doesn't have access to it. UA and CID can be sent from client // ip override. Look into headers for clients IP address, as opposed to IP address of host running lambda function params.uip = headers['x-forwarded-for'] || headers['x-bb-ip'] || '' // user agent override params.ua = params.ua || headers['user-agent'] || '' // REQUIRED: use given cid, or generate a new one as last resort. Generating should be avoided because one user can show up in GA multiple times. If user refresh page `n` times, you'll get `n` pageviews logged into GA from "different" users. Client should generate a uuid and store in cookies, local storage, or generate a fingerprint. Check simple-tracker client example params.cid = params.cid || uuidv4() console.info('proxying params:', params) const qs = querystring.stringify(params) try { const { ok, status, statusText } = await fetch(GA_ENDPOINT, { method: 'POST', headers: { 'Content-Type': 'image/gif' }, body: qs, }) if (!ok) { throw new Error(`HTTP error ${status}`) } console.info('googleanalytics status code', status, statusText) } catch (error) { console.info('googleanalytics error!', error) } } const handler = async function (event) { const origin = event.headers.origin || event.headers.Origin || '' const httpMethod = event.httpMethod.toUpperCase() console.log(`Received ${httpMethod} request from, origin: ${origin}`) const isOriginWhitelisted = originWhitelist.includes(origin) console.info('is whitelisted?', isOriginWhitelisted) const headers = { // 'Access-Control-Allow-Origin': '*', // allow all domains to POST. Use for localhost development only 'Access-Control-Allow-Origin': isOriginWhitelisted ? origin : originWhitelist[0], 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type,Accept', } // CORS (required if you use a different subdomain to host this function, or a different domain entirely) if (httpMethod === 'OPTIONS') { return { statusCode: 200, headers, body: '' } } // allow GET or POST, but only for whitelisted domains if ((httpMethod === 'GET' || httpMethod === 'POST') && isOriginWhitelisted) { await proxyToGoogleAnalytics(event) return { statusCode: 200, headers, body: '' } } return { statusCode: 404, headers, body: 'Not found' } } module.exports = { handler } // // Docs on GA endpoint and example params // // https://developers.google.com/analytics/devguides/collection/protocol/v1/devguide // // v: 1 // _v: j67 // a: 751874410 // t: pageview // _s: 1 // dl: https://nfeld.com/contact.html // dr: https://google.com // ul: en-us // de: UTF-8 // dt: Nikolay Feldman - Software Engineer // sd: 24-bit // sr: 1440x900 // vp: 945x777 // je: 0 // _u: blabla~ // jid: // gjid: // cid: 1837873423.1522911810 // tid: UA-116530991-1 // _gid: 1828045325.1524815793 // gtm: u4d // z: 1379041260 //