Socket
Socket
Sign inDemoInstall

cfga

Package Overview
Dependencies
Maintainers
1
Versions
5
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cfga - npm Package Compare versions

Comparing version 0.0.1 to 1.0.0

30

cfga.js

@@ -1,7 +0,9 @@

(function (ga, url, window, document, navigator) {
(function (window, document, navigator) {
var screen = window.screen,
encode = encodeURIComponent,
max = Math.max,
min = Math.min,
t = window.performance.timing;
//min = Math.min,
performance = window.performance,
t = performance && performance.timing;
filterNumber = function (num) { return isNaN(num) || num == Infinity || num < 0 ? void 0 : num; };

@@ -12,3 +14,3 @@ // sendGA: collect data and send.

// GA tid
'ga=' + ga,
'ga=' + window.ga_tid,
// Title

@@ -31,21 +33,21 @@ 'dt=' + encode(document.title),

// (window.onload)
'plt=' + encode(t.loadEventStart - t.navigationStart || 0),
'plt=' + filterNumber(t.loadEventStart - t.navigationStart || 0),
// dns: DNS Time
'dns=' + encode(t.domainLookupEnd - t.domainLookupStart || 0),
'dns=' + filterNumber(t,domainLookupEnd - t.domainLookupStart || 0),
// pdt: Page Dowenload Time
// start download time => finish download time
'pdt=' + encode(t.responseEnd - t.responseStart || 0),
'pdt=' + filterNumber(t,responseEnd - t.responseStart || 0),
// rrt: Redirect Time
'rrt=' + encode(t.redirectEnd - t.redirectStart || 0),
'rrt=' + filterNumber(t,redirectEnd - t.redirectStart || 0),
// tcp: TCP Time
'tcp=' + encode(t.connectEnd - t.connectStart || 0),
'tcp=' + filterNumber(t,connectEnd - t.connectStart || 0),
// srt: Server Response Time
// start request => server send first byte
// (TTFB - TCP - DNS)
'srt=' + encode(t.responseStart - t.requestStart || 0),
'srt=' + filterNumber(t,responseStart - t.requestStart || 0),
// dit: DOM Interactive Time
'dit=' + encode(t.domInteractive - t.domLoading || 0),
'dit=' + filterNumber(t,domInteractive - t.domLoading || 0),
// clt: Content Loading Time
// open the page => DOMContentLoaded
'clt=' + encode(t.domContentLoadedEventStart - t.navigationStart || 0),
'clt=' + filterNumber(t,domContentLoadedEventStart - t.navigationStart || 0),
'z=' + Date.now()

@@ -55,3 +57,3 @@ ];

window.__ga_img = new Image();
window.__ga_img.src = url + '?' + pv_data.join('&');;
window.__ga_img.src = window.ga_api + '?' + pv_data.join('&');
}

@@ -64,2 +66,2 @@

}
})(window.ga_tid, window.ga_api, window, document, navigator);
})(window, document, navigator);

@@ -1,1 +0,1 @@

!function(t,e,n,a,r){var o=n.screen,i=encodeURIComponent,d=Math.max,c=(Math.min,n.performance.timing);function g(){var g=["ga="+t,"dt="+i(a.title),"de="+i(a.characterSet||a.charset),"dr="+i(a.referrer),"ul="+(r.language||r.browserLanguage||r.userLanguage),"sd="+o.colorDepth+"-bit","sr="+o.width+"x"+o.height,"vp="+d(a.documentElement.clientWidth,n.innerWidth||0)+"x"+d(a.documentElement.clientHeight,n.innerHeight||0),"plt="+i(c.loadEventStart-c.navigationStart||0),"dns="+i(c.domainLookupEnd-c.domainLookupStart||0),"pdt="+i(c.responseEnd-c.responseStart||0),"rrt="+i(c.redirectEnd-c.redirectStart||0),"tcp="+i(c.connectEnd-c.connectStart||0),"srt="+i(c.responseStart-c.requestStart||0),"dit="+i(c.domInteractive-c.domLoading||0),"clt="+i(c.domContentLoadedEventStart-c.navigationStart||0),"z="+Date.now()];n.__ga_img=new Image,n.__ga_img.src=e+"?"+g.join("&")}"complete"===a.readyState?g():n.addEventListener("load",g)}(window.ga_tid,window.ga_api,window,document,navigator);
!function(t,e,r){var n=t.screen,a=encodeURIComponent,i=Math.max,o=t.performance,d=o&&o.timing;function m(){var o=["ga="+t.ga_tid,"dt="+a(e.title),"de="+a(e.characterSet||e.charset),"dr="+a(e.referrer),"ul="+(r.language||r.browserLanguage||r.userLanguage),"sd="+n.colorDepth+"-bit","sr="+n.width+"x"+n.height,"vp="+i(e.documentElement.clientWidth,t.innerWidth||0)+"x"+i(e.documentElement.clientHeight,t.innerHeight||0),"plt="+filterNumber(d.loadEventStart-d.navigationStart||0),"dns="+filterNumber(d,domainLookupEnd-d.domainLookupStart||0),"pdt="+filterNumber(d,responseEnd-d.responseStart||0),"rrt="+filterNumber(d,redirectEnd-d.redirectStart||0),"tcp="+filterNumber(d,connectEnd-d.connectStart||0),"srt="+filterNumber(d,responseStart-d.requestStart||0),"dit="+filterNumber(d,domInteractive-d.domLoading||0),"clt="+filterNumber(d,domContentLoadedEventStart-d.navigationStart||0),"z="+Date.now()];t.__ga_img=new Image,t.__ga_img.src=t.ga_api+"?"+o.join("&")}filterNumber=function(t){return isNaN(t)||t==1/0||t<0?void 0:t},"complete"===e.readyState?m():t.addEventListener("load",m)}(window,document,navigator);
{
"name": "cfga",
"version": "0.0.1",
"version": "1.0.0",
"description": "The Cloudflare Workers implementation of an async Google Analytics",

@@ -5,0 +5,0 @@ "main": "cfga.min.js",

# cloudflare-workers-async-google-analytics
[![Author Sukka](https://img.shields.io/badge/author-Sukka-b68469.svg?style=flat-square)](https://skk.moe)
[![License MIT](https://img.shields.io/github/license/sukkaw/cloudflare-workers-async-google-analytics.svg?style=flat-square)](./LICENSE)
![NPM Version](https://img.shields.io/npm/v/cfga)
[![Build with Cloudflare Workers](https://img.shields.io/badge/build%20with-cloudflare%20workers-f38020.svg?style=flat-square)](https://workers.cloudflare.com/)
![Gzip size of cfga.min.js](https://img.badgesize.io/sukkaw/cloudflare-workers-async-google-analytics/master/cfga.min.js.svg?compression=gzip&style=flat-square)
[![](https://data.jsdelivr.com/v1/package/npm/cfga/badge)](https://www.jsdelivr.com/package/npm/cfga)
The Cloudflare Workers implementation of an async Google Analytics
## Introduction
This project is based on [Google Analytics Measurement Protocol](https://developers.google.com/analytics/devguides/collection/protocol/v1/), using [Cloudflare Workers](https://workers.cloudflare.com/) with a less than 1KB gzipped tiny `cfga.min.js` to accelerate the Google Analytics, rather than a heavy (45KB gzipped) `analytics.js` from Google.
## Get Start
### 1. Import into Cloudflare Workers
Login into Cloudflare Dashboard and enter `Workers` App. Create a new script, delete default code in the editor, and then copy [the `woker.js` content](https://github.com/SukkaW/cloudflare-workers-async-google-analytics/blob/master/worker.js) into the editor. After saving the workers script, do not forget to register a route for the scripts.
Now you can test your workers with a simple HTTP request. You should able to see `403 Forbidden`. Then you can deploy the scripts.
### 2. Insert the `cfga.min.js` into your website
Just add those few lines of the code to your website, right before `</body>`. Do not forget to replace the default configuration with your own!
```html
<script>
window.ga_tid = "UA-XXXXX-Y"; // {String} The trackerID of your site.
window.ga_url = "https://example.com/xxx/"; // {String} The route of your cloudflare workers you just registered before.
</script>
<script src="https://cdn.jsdelivr.net/npm/cfga@1.0.0" async></script>
```
### 3. Watch this repo with `Releases Only`.
Click the `watch` button at the top of the repo and choose `Releases Only`, so you can get notice of release update in time.
## Advanced
### Data type the `cfga.min.js` collected and sent
Currently, `cloudflare-workers-async-google-analytics` and `cfga.min.js` only support collect those types of data listed below. If you want to collect more, you should use Google Analytics official track code.
- [`dl`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#dl): Document location URL
- [`uip`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#uip): User real IP
- [`ua`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#ua): User Agent
- [`dt`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#dt): Document Title
- [`de`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#de): Document Encoding
- [`dr`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#dr): Document Referrer
- [`ul`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#ul): User Language
- [`sd`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#sd): Screen Colors Depth
- [`sr`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#sr): Screen Resolution
- [`plt`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#plt): Page Load Time
- [`dns`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#dns): DNS Time
- [`pdt`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#pdt): Page Downloaad Time
- [`rrt`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#rrt): Redirect Response Time
- [`tcp`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#tcp): TCP Connect Time
- [`srt`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#srt): Server Response Time
- [`dit`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#dit): DOM Interactive Time
- [`clt`](https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#clt): Content Load Time
### Security
`cloudflare-workers-async-google-analytics` blocks those types of request by default:
- No `User-Agent` in request headers
- No `Referer` in request headers
- No Tracker ID given in request headers
- Use some other measurements from Cloudflare WAF
And if you want to restrict your workers only for your website, all you need to do is to edit a few lines of your workers:
- Launch Cloudflare Workers Editor again.
- You can see some commented out code at the first line like this:
```javascript
//const AllowedReferrer = 'skk.moe';
```
- replace your domain with `skk.moe`, then remove `//`.
> **Notice**: set `AllowedReferrer` value to `skk.moe` means all the subdomains of `skk.moe` will be allowed as well.
## Author
**cloudflare-workers-async-google-analytics** © [Sukka](https://github.com/SukkaW), Released under the [MIT](./LICENSE) License.<br>
Authored and maintained by Sukka with help from contributors ([list](https://github.com/SukkaW/cloudflare-workers-async-google-analytics/graphs/contributors)).
> [Personal Website](https://skk.moe) · [Blog](https://blog.skk.moe) · GitHub [@SukkaW](https://github.com/SukkaW) · Telegram Channel [@SukkaChannel](https://t.me/SukkaChannel) · Twitter [@isukkaw](https://twitter.com/isukkaw) · Keybase [@sukka](https://keybase.io/sukka)
//const AllowedReferrer = 'skk.moe';
const createUuid = () => {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {
let r = Math.random() * 16 | 0,
v = (c == 'x') ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
};
const encode = (data) => encodeURIComponent(decodeURIComponent(data));
addEventListener('fetch', (event) => {

@@ -22,2 +13,16 @@ event.respondWith(response(event));

async function response(event) {
const createUuid = () => {
let s = [];
const hexDigits = '0123456789abcdef';
for (let i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = '4'; // bits 12-15 of the time_hi_and_version field to 0010
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1); // bits 6-7 of the clock_seq_hi_and_reserved to 01
s[8] = s[13] = s[18] = s[23] = '-';
return s.join('');
};
const encode = (data) => encodeURIComponent(decodeURIComponent(data));
const url = new URL(event.request.url);

@@ -37,4 +42,8 @@

const Referer = getReqHeader('Referer');
const user_agent = getReqHeader('User-Agent');
const ga_tid = getQueryString('ga');
const hasUuid = getCookie('uuid');
const uuid = (hasUuid) ? getCookie('uuid') : createUuid();
const uuid = (hasUuid) ? hasUuid : createUuid();

@@ -44,14 +53,11 @@ let response;

let needBlock = false;
(!getReqHeader('Referer') || !getReqHeader('User-Agent') || !getQueryString('ga')) ? needBlock = true : needBlock = false;
(!Referer || !user_agent || !ga_tid) ? needBlock = true : needBlock = false;
if (typeof AllowedReferrer !== 'undefined' && AllowedReferrer !== null) {
if (AllowedReferrer && getReqHeader('Referer')) {
(!(getReqHeader('Referer').indexOf(AllowedReferrer) > -1)) ? needBlock = true : needBlock = false;
}
if (typeof AllowedReferrer !== 'undefined' && AllowedReferrer !== null && AllowedReferrer && Referer) {
(!(Referer.indexOf(AllowedReferrer) > -1)) ? needBlock = true : needBlock = false;
}
// Block Request that have no referer, no user-agent and no ga query.
if (needBlock) {
response = new Response('<html>403 Forbidden</html>', {
response = new Response('403 Forbidden', {
headers: { 'Content-Type': 'text/html' },

@@ -64,53 +70,8 @@ status: 403,

} else {
const pvData = [
// UA-XXXXXX-Y
'tid=' + encode(getQueryString('ga')),
// UUID Version 4
'cid=' + uuid,
// Document URL
'dl=' + encode(getReqHeader('Referer')),
// Real IP - Collect from CF-Connecting-IP
'uip=' + getReqHeader('CF-Connecting-IP'),
// Title
'dt=' + encode(getQueryString('dt')),
// Document Encoding
'de=' + encode(getQueryString('de')),
// Referrer
'dr=' + encode(getQueryString('dr')),
// Language
'ul=' + encode(getQueryString('ul')),
// Color Depth
'sd=' + encode(getQueryString('sd')),
// Screen Size
'sr=' + encode(getQueryString('sr')),
// Display
'vp=' + encode(getQueryString('vp')),
'z=' + getQueryString('z')
];
const pvData = `tid=${encode(ga_tid)}&cid=${uuid}&dl=${encode(Referer)}&uip=${getReqHeader('CF-Connecting-IP')}&ua=${user_agent}&dt=${encode(getQueryString('dt'))}&de=${encode(getQueryString('de'))}&dr=${encode(getQueryString('dr'))}&ul=${getQueryString('ul')}&sd=${getQueryString('sd')}&sr=${getQueryString('sr')}&vp=${getQueryString('vp')}`;
const perfData = [
// plt: Page Loading Time
'plt=' + getQueryString('plt'),
// dns: DNS Time
'dns=' + getQueryString('dns'),
// pdt: Page Dowenload Time
// start download time => finish download time
'pdt=' + getQueryString('pdt'),
// rrt: Redirect Time
'rrt=' + getQueryString('rrt'),
// tcp: TCP Time
'tcp=' + getQueryString('tcp'),
// srt: Server Response Time
// start request => server send first byte
// (TTFB - TCP - DNS)
'srt=' + getQueryString('srt'),
// dit: DOM Interactive Time
'dit=' + getQueryString('dit'),
// clt: Content Loading Time
// open the page => DOMContentLoaded
'clt=' + getQueryString('clt')
];
const perfData = `plt=${getQueryString('plt')}&dns=${getQueryString('dns')}&pdt=${getQueryString('pdt')}&rrt=${getQueryString('rrt')}&tcp=${getQueryString('tcp')}&srt=${getQueryString('srt')}&dit=${getQueryString('dit')}&clt=${getQueryString('clt')}`
const pvUrl = `https://www.google-analytics.com/collect?v=1&t=pageview&${pvData.join('&')}`;
const perfUrl = `https://www.google-analytics.com/collect?v=1&t=timing&${pvData.concat(perfData).join('&')}`
const pvUrl = `https://www.google-analytics.com/collect?v=1&t=pageview&${pvData}&z=${getQueryString('z')}`;
const perfUrl = `https://www.google-analytics.com/collect?v=1&t=timing&${pvData}&${perfData}&z=${getQueryString('z')}`

@@ -120,3 +81,3 @@ let parameter = {

'Host': 'www.google-analytics.com',
'User-Agent': getReqHeader('User-Agent'),
'User-Agent': user_agent,
'Accept': getReqHeader('Accept'),

@@ -129,8 +90,4 @@ 'Accept-Language': getReqHeader('Accept-Language'),

if (event.request.headers.has('Referer')) {
parameter.headers.Referer = getReqHeader('Referer');
}
if (event.request.headers.has('Origin')) {
parameter.headers.Origin = getReqHeader('Origin');
}
// To sent data to google analytics after response id finished
event.waitUntil(senData(pvUrl, perfUrl, parameter));

@@ -148,7 +105,4 @@ // Return an 204 to speed up: No need to download a gif

// To sent data to google analytics after response id finished
event.waitUntil(senData(pvUrl, perfUrl, parameter));
return response
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc