Add google analytics support
Add code to track performance metrics and events (password calculation).
This commit is contained in:
1 parent
6c6c02da4e
commit
d9bf30765f
12 files changed
+139
-11
No files matched your search
@@ -1,6 +1,8 @@
|
||||
#!/bin/sh
|
||||
set -e
|
||||
CLOSURE_COMPILER_URL="https://dl.google.com/closure-compiler/compiler-latest.zip"
|
||||
PROD_GOOGLE_ANALYTICS="UA-112154345-1"
|
||||
STAGE_GOOGLE_ANALYTCIS="UA-112154345-2"
|
||||
|
||||
install_closure() {
|
||||
wget $CLOSURE_COMPILER_URL -O /tmp/closure.zip
|
||||
@@ -11,6 +13,13 @@ install_closure() {
|
||||
}
|
||||
|
||||
build_package() {
|
||||
if [ -n "$TRAVIS_TAG" ]; then
|
||||
export GOOGLE_ANALYTICS_TAG="$PROD_GOOGLE_ANALYTICS"
|
||||
echo "Using prod google analytics tag"
|
||||
else
|
||||
export GOOGLE_ANALYTICS_TAG="$STAGE_GOOGLE_ANALYTCIS"
|
||||
echo "Using stage google analytics tag"
|
||||
fi
|
||||
PRODUCTION=1 npm run webpack
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
|
||||
var dataLayer;
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @return {number}
|
||||
* @nosideeffects
|
||||
*/
|
||||
Performance.prototype.mozNow = function() {};
|
||||
|
||||
/**
|
||||
* @return {number}
|
||||
* @nosideeffects
|
||||
*/
|
||||
Performance.prototype.oNow = function() {};
|
||||
|
||||
/**
|
||||
* @return {number}
|
||||
* @nosideeffects
|
||||
*/
|
||||
Performance.prototype.msNow = function() {};
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
declare const GOOGLE_ANALYTICS_TAG: string | undefined;
|
||||
|
||||
interface Window {
|
||||
dataLayer: any[];
|
||||
}
|
||||
|
||||
interface Performance {
|
||||
webkitNow(): number;
|
||||
mozNow(): number;
|
||||
oNow(): number;
|
||||
msNow(): number;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/* tslint:disable:no-empty */
|
||||
/* tslint:disable:only-arrow-functions */
|
||||
export let gtag: (...args: any[]) => void = () => {};
|
||||
|
||||
if (GOOGLE_ANALYTICS_TAG) {
|
||||
let gaElem = document.createElement("script");
|
||||
gaElem.async = true;
|
||||
let tag = GOOGLE_ANALYTICS_TAG;
|
||||
gaElem.src = `https://www.googletagmanager.com/gtag/js?id=${tag}`;
|
||||
let firstScript = document.getElementsByTagName("script")[0] as HTMLScriptElement;
|
||||
(firstScript.parentNode as HTMLElement).insertBefore(gaElem, firstScript);
|
||||
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
gtag = function() { window.dataLayer.push(arguments); };
|
||||
gtag("js", new Date());
|
||||
gtag("config", GOOGLE_ANALYTICS_TAG, {
|
||||
"custom_map": {"dimension1": "siteVersion"},
|
||||
"transport_type": "beacon"
|
||||
});
|
||||
}
|
||||
+8
-3
@@ -2,6 +2,7 @@ import { dellHddSolver, dellSolver, hddOldSolver } from "./dell";
|
||||
import { fsi20DecNewSolver, fsi20DecOldSolver, fsiHexSolver } from "./fsi";
|
||||
import { hpMiniSolver } from "./hpmini";
|
||||
import { insydeSolver } from "./insyde";
|
||||
import { monotonicTime } from "./performancePolyfill";
|
||||
import {
|
||||
phoenixFsiLSolver, phoenixFsiPSolver, phoenixFsiSolver,
|
||||
phoenixFsiSSolver, phoenixFsiXSolver, phoenixHPCompaqSolver, phoenixSolver
|
||||
@@ -10,7 +11,7 @@ import { samsungSolver } from "./samsung";
|
||||
import { sonySolver } from "./sony";
|
||||
import { Solver } from "./utils";
|
||||
|
||||
export type KeygenResult = [Solver, string[]];
|
||||
export type KeygenResult = [Solver, string[], number];
|
||||
|
||||
export const solvers: Solver[] = [
|
||||
sonySolver,
|
||||
@@ -35,6 +36,10 @@ export const solvers: Solver[] = [
|
||||
// NOTE: In future this function can change or even be removed
|
||||
export function keygen(serial: string): KeygenResult[] {
|
||||
return solvers
|
||||
.map((solver): KeygenResult => [solver, solver(serial)])
|
||||
.filter(([_, passwords]) => passwords !== undefined && passwords.length >= 1);
|
||||
.map((solver): KeygenResult => {
|
||||
let startTime = monotonicTime();
|
||||
let passwords = solver(serial);
|
||||
let calcTime = monotonicTime() - startTime;
|
||||
return [solver, passwords, calcTime];
|
||||
}).filter(([_, passwords]) => passwords !== undefined && passwords.length >= 1);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
import { monotonicTime } from "./performancePolyfill";
|
||||
|
||||
describe("Check performance.now polyfill", () => {
|
||||
it("monotonicTime should return number", () => {
|
||||
expect(typeof monotonicTime()).toEqual("number");
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
|
||||
function makeMonotonicTime(): () => number {
|
||||
if (typeof performance !== "undefined" && performance) {
|
||||
let nowFun = performance.now ||
|
||||
performance.webkitNow ||
|
||||
performance.mozNow ||
|
||||
performance.oNow ||
|
||||
performance.msNow;
|
||||
|
||||
if (nowFun) {
|
||||
return nowFun.bind(performance);
|
||||
} else {
|
||||
return Date.now;
|
||||
}
|
||||
} else {
|
||||
return Date.now;
|
||||
}
|
||||
}
|
||||
|
||||
export const monotonicTime = makeMonotonicTime();
|
||||
@@ -1,6 +1,5 @@
|
||||
import { keygen, KeygenResult } from "./keygen";
|
||||
|
||||
/// <reference types="dom" />
|
||||
import { gtag } from "./googleAnalytics";
|
||||
import { keygen, KeygenResult, solvers } from "./keygen";
|
||||
|
||||
let form = document.getElementById("form_id") as HTMLFormElement;
|
||||
let serialInput = document.getElementById("serial_id") as HTMLInputElement;
|
||||
@@ -11,10 +10,10 @@ let answerElement = document.getElementById("answer") as HTMLDivElement;
|
||||
function renderResult(results: KeygenResult[]): void {
|
||||
let table = document.createElement("table");
|
||||
table.classList.add("answer_table");
|
||||
results.forEach(([solver, passwords]) => {
|
||||
results.forEach(([solver, passwords, _]) => {
|
||||
let trElem = document.createElement("tr");
|
||||
let tdNameElem = document.createElement("td");
|
||||
tdNameElem.appendChild(document.createTextNode(solver.biosName));
|
||||
tdNameElem.appendChild(document.createTextNode(solver.description));
|
||||
trElem.appendChild(tdNameElem);
|
||||
let tdElem = document.createElement("td");
|
||||
passwords.forEach((pwd, index) => {
|
||||
@@ -29,6 +28,31 @@ function renderResult(results: KeygenResult[]): void {
|
||||
answerElement.appendChild(table);
|
||||
}
|
||||
|
||||
function trackResult(serial: string): KeygenResult[] {
|
||||
let result = keygen(serial);
|
||||
if (GOOGLE_ANALYTICS_TAG) {
|
||||
let eventParams: {[key: string]: boolean} = {};
|
||||
solvers.forEach((solver) => {
|
||||
eventParams[solver.biosName] = false;
|
||||
});
|
||||
|
||||
result.forEach(([solver, _, time]) => {
|
||||
eventParams[solver.biosName] = true;
|
||||
|
||||
// send calculation timing report
|
||||
gtag("event", "timing_complete", {
|
||||
"name": "bios_keygen",
|
||||
"value": Math.round(time),
|
||||
"event_category": solver.biosName
|
||||
});
|
||||
});
|
||||
|
||||
// send event about calculation
|
||||
gtag("event", "bios_keygen", eventParams);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
form.addEventListener("submit", (event) => {
|
||||
if (event.preventDefault) {
|
||||
event.preventDefault();
|
||||
@@ -36,7 +60,7 @@ form.addEventListener("submit", (event) => {
|
||||
event.returnValue = false;
|
||||
}
|
||||
answerElement.innerHTML = ""; // remove old table
|
||||
let results = keygen(serialInput.value);
|
||||
let results = trackResult(serialInput.value);
|
||||
if (results.length > 0) {
|
||||
tryThis.style.display = "";
|
||||
dellNote.style.display = "";
|
||||
|
||||
+1
-1
@@ -13,7 +13,7 @@ export interface Solver {
|
||||
(code: string): string[];
|
||||
readonly biosName: string;
|
||||
readonly examples?: string[];
|
||||
readonly description?: string;
|
||||
readonly description: string;
|
||||
validator(code: string): boolean;
|
||||
cleaner(code: string): string;
|
||||
keygen(code: string): string[];
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"lib": ["dom", "es5"],
|
||||
"target": "es3",
|
||||
"noImplicitAny": true,
|
||||
"noImplicitReturns": true,
|
||||
|
||||
+12
-1
@@ -4,12 +4,20 @@ const ClosureCompilerPlugin = require('webpack-closure-compiler');
|
||||
const HtmlWebpackPlugin = require('html-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
const CleanWebpackPlugin = require('clean-webpack-plugin');
|
||||
const webpack = require('webpack');
|
||||
|
||||
function makeClosureCompiler() {
|
||||
const externDir = path.join(__dirname, "externs");
|
||||
const externs = [
|
||||
path.join(externDir, "googleAnalytics.js"),
|
||||
path.join(externDir, "performance.js")
|
||||
];
|
||||
|
||||
var pluginOptions = {
|
||||
compiler: {
|
||||
compilation_level: "ADVANCED",
|
||||
create_source_map: true
|
||||
create_source_map: true,
|
||||
externs: externs
|
||||
},
|
||||
concurrency: os.cpus().length
|
||||
};
|
||||
@@ -29,6 +37,9 @@ var plugins = [
|
||||
to: 'assets/'
|
||||
}
|
||||
]),
|
||||
new webpack.DefinePlugin({
|
||||
GOOGLE_ANALYTICS_TAG: JSON.stringify(process.env.GOOGLE_ANALYTICS_TAG)
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
minify: {
|
||||
collapseWhitespace: true,
|
||||
|
||||
Reference in new issue
Block a user