Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add countly metrics #309

Merged
merged 12 commits into from
Dec 5, 2022
850 changes: 521 additions & 329 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,8 @@
},
"dependencies": {
"@dutu/rate-limiter": "github:dutu/rate-limiter#v1.3.1",
"countly-sdk-web": "^22.6.2",
SgtPooki marked this conversation as resolved.
Show resolved Hide resolved
"ipfs-http-client": "^58.0.1",
"url-ponyfill": "^0.5.10"
},
"devDependencies": {
Expand Down
24 changes: 24 additions & 0 deletions src/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,30 @@

declare module '@dutu/rate-limiter'
declare module 'ipfs-geoip'
declare module 'countly-sdk-web' {
/**
* From https://support.count.ly/hc/en-us/articles/360037441932-Web-analytics-JavaScript-#minimal-setup
*/
interface CountlyEventData {
key: string
count: number
sum: number
segmentation: Record<string, string | number>
}
type CountlyEventQueueItem = [string, CountlyEventData] | [eventName: string, key: string] | [eventName: string]
interface CountlyWebSdk {
SgtPooki marked this conversation as resolved.
Show resolved Hide resolved
group_features: (arg0: { all: string[] }) => unknown
add_consent: (arg0: string) => unknown
require_consent: boolean
init: () => void
add_event: (event: { key: string, count: number, sum: number, dur: number }) => void
app_key: string
url: string
q?: CountlyEventQueueItem[]
}
declare const Countly: CountlyWebSdk
export default Countly
}

// declare global {
/**
Expand Down
31 changes: 18 additions & 13 deletions src/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,24 @@ <h1 class='f3 fw2 montserrat aqua ttu ma0'>Public Gateways</h1>
</header>

<div class="ph4-l pt4-l">
<div id="origin-warning" class="f5 pa2 tl">
<p>SECURITY NOTES</p>
<ul class="pl3">
<li>Avoid storing sensitive data (or providing credentials) on websites loaded via gateways marked with <big>⚠️ </big><br/>
These are legacy gateways for fetching standalone data, not designed to serve dapps/websites.<br/>
<strong>They do not provide <a href="https://docs.ipfs.io/how-to/address-ipfs-on-web/#path-gateway">origin isolation</a></strong>.
</li>
<li class="pt2">
The list contains gateways operated by various parties, coordinated by loose mutual consensus, <strong>without a central governing authority</strong>.<br/>
Protocol Labs operates and is responsible for only two of the listed gateways: <code>ipfs.io</code> and <code>dweb.link</code>.
</li>
</ul>
</div>
<div id="origin-warning" class="f5 pa2 tl">
<p>SECURITY NOTES</p>
<ul class="pl3">
<li>Avoid storing sensitive data (or providing credentials) on websites loaded via gateways marked with <big>⚠️ </big><br/>
These are legacy gateways for fetching standalone data, not designed to serve dapps/websites.<br/>
<strong>They do not provide <a href="https://docs.ipfs.io/how-to/address-ipfs-on-web/#path-gateway">origin isolation</a></strong>.
</li>
<li class="pt2">
The list contains gateways operated by various parties, coordinated by loose mutual consensus, <strong>without a central governing authority</strong>.<br/>
Protocol Labs operates and is responsible for only two of the listed gateways: <code>ipfs.io</code> and <code>dweb.link</code>.
</li>
</ul>
</div>
<div id="metrics-notification" class="hidden">
<span>We're collecting <a href="https://github.com/ipfs/ipfs-gui/issues/125">web-vitals, pageview, and other metrics</a> in order to improve and prioritize our work on IPFS and its public gateways.
Please consent to the collection of these metrics to assist in our efforts!</span>
<button id="metrics-notification-accept">Contribute to the improvement of IPFS</button>
</div>
<div id="checker.stats" class="Stats monospace f6"></div>
<div id="checker.results" class="Results monospace f6">
<div class="Node Header">
Expand Down
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { Checker } from './Checker'
import gateways from './gateways.json'

import { loadCountly } from './metrics'
import { Log } from './Log'

loadCountly()
const log = new Log('App index')

window.checker = new Checker()
Expand Down
56 changes: 56 additions & 0 deletions src/metrics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import Countly from 'countly-sdk-web'

Countly.q = Countly.q ?? []

/**
* metrics consent and GDPR stuffs
*
* @see https://support.count.ly/hc/en-us/articles/360037441932-Web-analytics-JavaScript-#features-for-consent
*/
Countly.require_consent = true
Countly.app_key = '3c2c0819434074fc4d339ddd8e112a1e741ecb72'
Countly.url = 'https://countly.ipfs.io'

// Start pushing function calls to queue
// Track sessions automatically (recommended)
Countly.q.push(['track_sessions'])

// track web page views automatically (recommended)
Countly.q.push(['track_pageview'])

const metricsConsent = localStorage.getItem('metrics_consent')
function addConsent (): void {
Countly.add_consent('all')
const banner = document.querySelector('#metrics-notification')
banner?.classList.add('hidden')
localStorage.setItem('metrics_consent', 'true')
}

/**
SgtPooki marked this conversation as resolved.
Show resolved Hide resolved
* Display the consent banner and handle the user's choice
*/
function displayConsentBanner (): void {
const banner = document.querySelector('#metrics-notification')
SgtPooki marked this conversation as resolved.
Show resolved Hide resolved
banner?.classList.remove('hidden')
const acceptButton = document.querySelector('#metrics-notification-accept')
acceptButton?.addEventListener('click', addConsent)
SgtPooki marked this conversation as resolved.
Show resolved Hide resolved
}

function loadCountly (): void {
Countly.init()
Countly.group_features({
all: ['sessions', 'events', 'views'] // , 'scrolls', 'clicks', 'forms', 'crashes', 'attribution', 'users']
})
if (metricsConsent === 'true') {
addConsent()
} else {
displayConsentBanner()
}
}

document.querySelector('#metrics-notification')

export {
loadCountly,
Countly
}
36 changes: 36 additions & 0 deletions src/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,39 @@ div#origin-warning ol, div#origin-warning p, div#origin-warning ul {
div#checker\.results .Node:nth-child(1) .Link {
padding-left: 1em;
}

/**
* Consent notification for metrics collection
* Should be a color that is not too bright, but still visible
*/
div#metrics-notification {
background-color: #ECF5F7;
justify-content: center;
display: flex;
flex-direction: column;
align-items: center;
border-left: 4px solid #5EC9CE;
margin: 1rem 0;
padding: 1rem 0;
}

div#metrics-notification.hidden {
display: none;
}

div#metrics-notification span {
/* color: white; */
padding: 1em;
}

div#metrics-notification button#metrics-notification-accept {
background-color: #57C7CC;
border: none;
color: white;
padding: 1em;
/* margin: 0 1em; */
/* width: auto; */
flex-basis: fit-content;
flex-shrink: 1;
cursor: pointer;
}