-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: analytics (#20) fix: close panel on row unmount
- Loading branch information
Showing
15 changed files
with
254 additions
and
14 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,3 +5,4 @@ node_modules/ | |
*.zip | ||
roadmap.md | ||
yarn-error.log | ||
src/secrets.json |
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 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 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
import Error = chrome.cast.Error; | ||
|
||
const GA_ENDPOINT = 'https://www.google-analytics.com/mp/collect'; | ||
const GA_DEBUG_ENDPOINT = 'https://www.google-analytics.com/debug/mp/collect'; | ||
import secrets from '../secrets.json'; | ||
// File taken from https://github.com/GoogleChrome/chrome-extensions-samples/blob/main/functional-samples/tutorial.google-analytics/scripts/google-analytics.js | ||
// Get via https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#recommended_parameters_for_reports | ||
const MEASUREMENT_ID = secrets.measurement_id; | ||
const API_SECRET = secrets.api_secret; | ||
const DEFAULT_ENGAGEMENT_TIME_MSEC = 100; | ||
|
||
// Duration of inactivity after which a new session is created | ||
const SESSION_EXPIRATION_IN_MIN = 30; | ||
|
||
type Params = { | ||
session_id?: string; | ||
engagement_time_msec?: number; | ||
[key: string]: unknown; | ||
}; | ||
|
||
class Analytics { | ||
debug = false; | ||
|
||
constructor(debug = false) { | ||
this.debug = debug; | ||
} | ||
|
||
// Returns the client id, or creates a new one if one doesn't exist. | ||
// Stores client id in local storage to keep the same client id as long as | ||
// the extension is installed. | ||
async getOrCreateClientId() { | ||
let { clientId } = await chrome.storage.local.get('clientId'); | ||
if (!clientId) { | ||
// Generate a unique client ID, the actual value is not relevant | ||
clientId = self.crypto.randomUUID(); | ||
await chrome.storage.local.set({ clientId }); | ||
} | ||
return clientId; | ||
} | ||
|
||
// Returns the current session id, or creates a new one if one doesn't exist or | ||
// the previous one has expired. | ||
async getOrCreateSessionId() { | ||
// Use storage.session because it is only in memory | ||
let { sessionData } = await chrome.storage.session.get('sessionData'); | ||
const currentTimeInMs = Date.now(); | ||
// Check if session exists and is still valid | ||
if (sessionData && sessionData.timestamp) { | ||
// Calculate how long ago the session was last updated | ||
const durationInMin = | ||
(currentTimeInMs - sessionData.timestamp) / 60000; | ||
// Check if last update lays past the session expiration threshold | ||
if (durationInMin > SESSION_EXPIRATION_IN_MIN) { | ||
// Clear old session id to start a new session | ||
sessionData = null; | ||
} else { | ||
// Update timestamp to keep session alive | ||
sessionData.timestamp = currentTimeInMs; | ||
await chrome.storage.session.set({ sessionData }); | ||
} | ||
} | ||
if (!sessionData) { | ||
// Create and store a new session | ||
sessionData = { | ||
session_id: currentTimeInMs.toString(), | ||
timestamp: currentTimeInMs.toString() | ||
}; | ||
await chrome.storage.session.set({ sessionData }); | ||
} | ||
return sessionData.session_id; | ||
} | ||
|
||
// Fires an event with optional params. Event names must only include letters and underscores. | ||
async fireEvent(name: string, params: Params = {}) { | ||
// Configure session id and engagement time if not present, for more details see: | ||
// https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#recommended_parameters_for_reports | ||
if (!params.session_id) { | ||
params.session_id = await this.getOrCreateSessionId(); | ||
} | ||
if (!params.engagement_time_msec) { | ||
params.engagement_time_msec = DEFAULT_ENGAGEMENT_TIME_MSEC; | ||
} | ||
|
||
try { | ||
const response = await fetch( | ||
`${ | ||
this.debug ? GA_DEBUG_ENDPOINT : GA_ENDPOINT | ||
}?measurement_id=${MEASUREMENT_ID}&api_secret=${API_SECRET}`, | ||
{ | ||
method: 'POST', | ||
body: JSON.stringify({ | ||
client_id: await this.getOrCreateClientId(), | ||
events: [ | ||
{ | ||
name, | ||
params | ||
} | ||
] | ||
}) | ||
} | ||
); | ||
if (!this.debug) { | ||
return; | ||
} | ||
console.log(await response.text()); | ||
} catch (e) { | ||
console.error( | ||
'Google Analytics request failed with an exception', | ||
e | ||
); | ||
} | ||
} | ||
|
||
// Fire a page view event. | ||
async firePageViewEvent( | ||
pageTitle: string, | ||
pageLocation: string, | ||
additionalParams: Params = {} | ||
) { | ||
return this.fireEvent('page_view', { | ||
page_title: pageTitle, | ||
page_location: pageLocation, | ||
...additionalParams | ||
}); | ||
} | ||
|
||
// Fire an error event. | ||
async fireErrorEvent(error: Error, additionalParams: Params = {}) { | ||
// Note: 'error' is a reserved event name and cannot be used | ||
// see https://developers.google.com/analytics/devguides/collection/protocol/ga4/reference?client_type=gtag#reserved_names | ||
return this.fireEvent('extension_error', { | ||
...error, | ||
...additionalParams | ||
}); | ||
} | ||
} | ||
|
||
export default new Analytics(); //process.env.NODE_ENV === 'development'); |
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 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 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 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 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 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 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
Oops, something went wrong.