Skip to content

Instantly share code, notes, and snippets.

@burakeregar
Forked from AlbericoD/analytics.d.ts
Last active July 6, 2023 00:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save burakeregar/a2d3e87591389e77ab58e27c72655eff to your computer and use it in GitHub Desktop.
Save burakeregar/a2d3e87591389e77ab58e27c72655eff to your computer and use it in GitHub Desktop.
Google analytics Overwolf
interface LocalSession {
sessionId?: string;
timestamp?: number;
}
interface PageViewParams {
hit: "page_view";
params: {
page_location: string;
page_title: string;
};
}
interface PlayerMapParams {
hit: "player_map_engagement";
params: {
category: "controls" | "timeline";
event_action:
| "play"
| "pause"
| "forward"
| "backward"
| "speed_change"
| "slider_change"
| "backward_15"
| "forward_15"
| "loop"
| "previous_match"
| "next_match"
| "seek"
| "attach_camera";
event_label:
| "button"
| "slider"
| "keyboard"
| "mouse"
| "touch"
| "unknown";
value?: number | string | boolean;
};
}
interface HeaderButtonParams {
hit: "header_button";
params: {
event_action: "click";
event_label: "open_store" | "open_discord" | "close_app";
};
}
interface TimeLineParams {
hit: "timeline";
params: {
event_action: "focus" | "play";
event_label: "full" | "simple";
};
}
interface SettingsParams {
hit: "settings";
params: {
event_action: "slider" | "hotkey";
option_name: string;
value: string;
};
}
interface MatchesParams {
hit: "matches";
params: {
event_action: "focus" | "quantity_matches";
value?: number;
};
}
type UseMeasurementProtocolArgs =
| PageViewParams
| PlayerMapParams
| HeaderButtonParams
| TimeLineParams
| SettingsParams
| MatchesParams;
import { v4 as uuidv4 } from "uuid";
import { getMachineId } from "./useMachineId";
import { useCallback, useEffect, useState } from "react";
const __TRACKING_SESSION_ID__ = "__OVERWOLF_HOOKS__TRACKING_SESSION_ID__";
const __TRACKING_SESSION_ID_MAX_AGE__ = 30 * 60 * 1000; // 30 minutes -> @see What counts as a session https://support.google.com/analytics/answer/9191807
const GTAG_PROPERTIES = {
COLLECT_URL: `https://www.google-analytics.com/${
process.env.NODE_ENV === "development" ? "debug/" : ""
}mp/collect`,
MEASUREMENT_ID: process.env.REACT_APP_MEASUREMENT_ID!, // your gtag id (ex: G-XXXXXXXXXX)
API_SECRET: process.env.REACT_APP_GTAG_API_SECRET!, // your gtag api secret (ex: abcdefghijkLMNsdfghijk)
DATA_SOURCE: "overwolf", //https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#ds
};
//About the Measurement Protocol Parameters @see https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters
const FETCH_URL =
`${GTAG_PROPERTIES.COLLECT_URL}?measurement_id=${GTAG_PROPERTIES.MEASUREMENT_ID}&api_secret=${GTAG_PROPERTIES.API_SECRET}&ds=${GTAG_PROPERTIES.DATA_SOURCE}`.replace(
/\s/g,
""
);
/*
Recommended parameters for reports
In order for user activity to display in standard reports like Realtime, engagement_time_msec and session_id must be supplied as part of the params for an event.
@see https://developers.google.com/analytics/devguides/collection/protocol/ga4/sending-events?client_type=gtag#recommended_parameters_for_reports
*/
function useRealTimeEvent() {
//While session_start is a reserved event name, creating a new session_id will effectively create a new session without the need to send session_start.
const [sessionId, setSessionId] = useState<string>();
useEffect(() => {
const mainWindow =
process.env.NODE_ENV === "development"
? window
: overwolf.windows.getMainWindow();
const isThisSession = JSON.parse(
mainWindow.localStorage.getItem(__TRACKING_SESSION_ID__) ?? "{}"
) as LocalSession;
const isValidSession =
isThisSession.sessionId &&
isThisSession.timestamp &&
isThisSession.timestamp + __TRACKING_SESSION_ID_MAX_AGE__ > Date.now();
if (isValidSession) {
setSessionId(isThisSession.sessionId);
} else {
const session = {
id: uuidv4(),
timestamp: Date.now(),
};
mainWindow.localStorage.setItem(
__TRACKING_SESSION_ID__,
JSON.stringify(session)
);
setSessionId(session.id);
}
return () => {
mainWindow.localStorage.removeItem(__TRACKING_SESSION_ID__);
};
}, []);
return {
engagement_time_msec: "100",
session_id: sessionId,
};
}
const useMeasurementProtocol = () => {
const realTimeEvent = useRealTimeEvent();
const dispatchEvent = useCallback(
async ({ hit, params }: UseMeasurementProtocolArgs) => {
try {
if (process.env.NODE_ENV === "development") {
console.log("Google Analytics is not available in development mode", {
hit,
params,
});
return;
}
const machineId = await getMachineId();
const body = JSON.stringify({
client_id: machineId, // its the same of user_id A unique identifier for a client. This should be a random UUID that is associated with particular user, device, or browser instance.
user_id: machineId, //Optional. A unique identifier for a user. See User-ID for cross-platform analysis for more information on this identifier.,
events: [
{
name: hit,
params: {
...params,
...realTimeEvent,
},
},
],
});
const result = await fetch(FETCH_URL, {
method: "POST",
body,
});
return result;
} catch (error) {
throw new Error(
`Error on dispatching event to Google Analytics: ${error}`
);
}
},
[realTimeEvent]
);
return { dispatchEvent };
};
export { useMeasurementProtocol };
import { useEffect, useState } from "react";
import { v4 as uuidv4 } from "uuid";
const MACHINE_ID_KEY = "__OVERWOLF_HOOKS__OVERWOLF_MACHINE_ID__KEY";
const getMachineId = async (): Promise<string> => {
return new Promise((resolve, reject) => {
const backgroundWindow = overwolf.windows.getMainWindow();
const machineId = backgroundWindow.localStorage.getItem(MACHINE_ID_KEY);
if (machineId) {
resolve(machineId);
}
overwolf.profile.getCurrentUser((result) => {
if (result.success) {
backgroundWindow.localStorage.setItem(
MACHINE_ID_KEY,
result.machineId!
);
resolve(result.machineId!);
} else {
var randomId = uuidv4();
window.localStorage.setItem(
MACHINE_ID_KEY,
randomId
);
resolve(randomId);
}
});
});
};
export { getMachineId };
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment