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

Switched most uses of track to GA4 #6016

Merged
merged 3 commits into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import * as scopes from "./scopes";
import { clearCredentials } from "./defaultCredentials";
import { v4 as uuidv4 } from "uuid";
import { randomBytes, createHash } from "crypto";
import { track } from "./track";
import { trackGA4 } from "./track";
import {
authOrigin,
authProxyOrigin,
Expand Down Expand Up @@ -444,7 +444,7 @@ async function loginRemotely(): Promise<UserCredentials> {
codeVerifier
);

void track("login", "google_remote");
void trackGA4("login", { method: "google_remote" });

return {
user: jwt.decode(tokens.id_token!) as User,
Expand All @@ -468,7 +468,7 @@ async function loginWithLocalhostGoogle(port: number, userHint?: string): Promis
getTokensFromAuthorizationCode
);

void track("login", "google_localhost");
void trackGA4("login", { method: "google_localhost" });
// getTokensFromAuthoirzationCode doesn't handle the --token case, so we know we'll
// always have an id_token.
return {
Expand All @@ -489,7 +489,7 @@ async function loginWithLocalhostGitHub(port: number): Promise<string> {
successTemplate,
getGithubTokensFromAuthorizationCode
);
void track("login", "google_localhost");
void trackGA4("login", { method: "github_localhost" });
return tokens;
}

Expand Down
25 changes: 20 additions & 5 deletions src/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { loadRC } from "./rc";
import { Config } from "./config";
import { configstore } from "./configstore";
import { detectProjectRoot } from "./detectProjectRoot";
import { track, trackEmulator } from "./track";
import { trackEmulator, trackGA4 } from "./track";
import { selectAccount, setActiveAccount } from "./auth";
import { getFirebaseProject } from "./management/projects";
import { requireAuth } from "./requireAuth";
Expand Down Expand Up @@ -202,7 +202,12 @@ export class Command {
);
}
const duration = Math.floor((process.uptime() - start) * 1000);
const trackSuccess = track(this.name, "success", duration);
const trackSuccess = trackGA4("command_execution", {
command_name: this.name,
result: "success",
duration,
interactive: getInheritedOption(options, "nonInteractive") ? "false" : "true",
});
if (!isEmulator) {
await withTimeout(5000, trackSuccess);
} else {
Expand Down Expand Up @@ -236,8 +241,15 @@ export class Command {
await withTimeout(
5000,
Promise.all([
track(this.name, "error", duration),
track(err.exit === 1 ? "Error (User)" : "Error (Unexpected)", "", duration),
trackGA4(
"command_execution",
{
command_name: this.name,
result: "error",
interactive: getInheritedOption(options, "nonInteractive") ? "false" : "true",
},
duration
),
isEmulator
? trackEmulator("command_error", {
command_name: this.name,
Expand Down Expand Up @@ -400,7 +412,10 @@ export function validateProjectId(project: string): void {
if (PROJECT_ID_REGEX.test(project)) {
return;
}
track("Project ID Check", "invalid");
trackGA4("error", {
error_type: "Error (User)",
details: "Invalid project ID",
});
const invalidMessage = "Invalid project id: " + clc.bold(project) + ".";
if (project.toLowerCase() !== project) {
// Attempt to be more helpful in case uppercase letters are used.
Expand Down
13 changes: 10 additions & 3 deletions src/commands/ext-install.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
import { getRandomString } from "../extensions/utils";
import { requirePermissions } from "../requirePermissions";
import * as utils from "../utils";
import { track } from "../track";
import { trackGA4 } from "../track";
import { confirm } from "../prompt";
import { Options } from "../options";
import * as manifest from "../extensions/manifest";
Expand Down Expand Up @@ -96,11 +96,18 @@ export const command = new Command("ext:install [extensionName]")
// Should parse spec locally so we don't need project ID.
source = await createSourceFromLocation(needProjectId({ projectId }), extensionName);
await displayExtInfo(extensionName, "", source.spec);
void track("Extension Install", "Install by Source", options.interactive ? 1 : 0);
void trackGA4("extension_added_to_manifest", {
published: "local",
interactive: options.nonInteractive ? "false" : "true",
});
} else {
void track("Extension Install", "Install by Extension Ref", options.interactive ? 1 : 0);
extensionName = await canonicalizeRefInput(extensionName);
extensionVersion = await extensionsApi.getExtensionVersion(extensionName);

void trackGA4("extension_added_to_manifest", {
published: extensionVersion.listing?.state === "APPROVED" ? "published" : "uploaded",
interactive: options.nonInteractive ? "false" : "true",
});
await infoExtensionVersion({
extensionName,
extensionVersion,
Expand Down
7 changes: 5 additions & 2 deletions src/deploy/functions/checkIam.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { flattenArray } from "../../functional";
import * as iam from "../../gcp/iam";
import * as args from "./args";
import * as backend from "./backend";
import { track } from "../../track";
import { trackGA4 } from "../../track";
import * as utils from "../../utils";

import { getIamPolicy, setIamPolicy } from "../../gcp/resourceManager";
Expand Down Expand Up @@ -101,7 +101,10 @@ export async function checkHttpIam(
}

if (!passed) {
void track("Error (User)", "deploy:functions:http_create_missing_iam");
void trackGA4("error", {
error_type: "Error (User)",
details: "deploy:functions:http_create_missing_iam",
});
throw new FirebaseError(
`Missing required permission on project ${bold(
context.projectId
Expand Down
6 changes: 4 additions & 2 deletions src/deploy/hosting/prepare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Context } from "./context";
import { Options } from "../../options";
import { HostingOptions } from "../../hosting/options";
import { assertExhaustive, zipIn } from "../../functional";
import { track } from "../../track";
import { trackGA4 } from "../../track";
import * as utils from "../../utils";
import { HostingSource, RunRewrite } from "../../firebaseConfig";
import * as backend from "../functions/backend";
Expand Down Expand Up @@ -137,7 +137,9 @@ export async function prepare(context: Context, options: HostingOptions & Option
labels,
};
const [, versionName] = await Promise.all([
track("hosting_deploy", config.webFramework || "classic"),
trackGA4("hosting_version", {
framework: config.webFramework || "classic",
}),
api.createVersion(config.site, version),
]);
return versionName;
Expand Down
21 changes: 14 additions & 7 deletions src/deploy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ import * as clc from "colorette";
import { logger } from "../logger";
import { hostingOrigin } from "../api";
import { bold, underline, white } from "colorette";
import { has, includes, each } from "lodash";
import { includes, each } from "lodash";
import { needProjectId } from "../projectUtils";
import { logBullet, logSuccess, consoleUrl, addSubdomain } from "../utils";
import { FirebaseError } from "../error";
import { track } from "../track";
import { AnalyticsParams, trackGA4 } from "../track";
import { lifecycleHooks } from "./lifecycleHooks";
import * as experiments from "../experiments";
import * as HostingTarget from "./hosting";
Expand Down Expand Up @@ -119,12 +119,19 @@ export const deploy = async function (
await chain(releases, context, options, payload);
await chain(postdeploys, context, options, payload);

if (has(options, "config.notes.databaseRules")) {
await track("Rules Deploy", options.config.notes.databaseRules);
}

const duration = Date.now() - startTime;
await track("Product Deploy", [...targetNames].sort().join(","), duration);
const analyticsParams: AnalyticsParams = {
interactive: options.nonInteractive ? "false" : "true",
};

Object.keys(TARGETS).reduce((accum, t) => {
accum[t] = "false";
return accum;
}, analyticsParams);
for (const t of targetNames) {
analyticsParams[t] = "true";
}
await trackGA4("product_deploy", analyticsParams, duration);

logger.info();
logSuccess(bold(underline("Deploy complete!")));
Expand Down
4 changes: 1 addition & 3 deletions src/emulator/controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as path from "path";
import * as fsConfig from "../firestore/fsConfig";

import { logger } from "../logger";
import { track, trackEmulator } from "../track";
import { trackEmulator } from "../track";
import * as utils from "../utils";
import { EmulatorRegistry } from "./registry";
import {
Expand Down Expand Up @@ -401,7 +401,6 @@ export async function startAll(
const name = instance.getName();

// Log the command for analytics
void track("Emulator Run", name);
void trackEmulator("emulator_run", {
emulator_name: name,
is_demo_project: String(isDemoProject),
Expand All @@ -421,7 +420,6 @@ export async function startAll(
// since we originally mistakenly reported emulators:start events
// for each emulator, by reporting the "hub" we ensure that our
// historical data can still be viewed.
void track("emulators:start", "hub");
await startEmulator(hub);
}

Expand Down
4 changes: 1 addition & 3 deletions src/emulator/functionsEmulator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { EventEmitter } from "events";

import { Account } from "../types/auth";
import { logger } from "../logger";
import { track, trackEmulator } from "../track";
import { trackEmulator } from "../track";
import { Constants } from "./constants";
import { EmulatorInfo, EmulatorInstance, Emulators, FunctionsExecutionMode } from "./types";
import * as chokidar from "chokidar";
Expand Down Expand Up @@ -63,7 +63,6 @@ import { resolveBackend } from "../deploy/functions/build";
import { setEnvVarsForEmulators } from "./env";
import { runWithVirtualEnv } from "../functions/python";

const EVENT_INVOKE = "functions:invoke"; // event name for UA
const EVENT_INVOKE_GA4 = "functions_invoke"; // event name GA4 (alphanumertic)

/*
Expand Down Expand Up @@ -1551,7 +1550,6 @@ export class FunctionsEmulator implements EmulatorInstance {
}
}
// For analytics, track the invoked service
void track(EVENT_INVOKE, getFunctionService(trigger));
void trackEmulator(EVENT_INVOKE_GA4, {
function_service: getFunctionService(trigger),
});
Expand Down
6 changes: 4 additions & 2 deletions src/ensureApiEnabled.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { bold } from "colorette";

import { track } from "./track";
import { trackGA4 } from "./track";
import { serviceUsageOrigin } from "./api";
import { Client } from "./apiv2";
import * as utils from "./utils";
Expand Down Expand Up @@ -91,7 +91,9 @@ async function pollCheckEnabled(
});
const isEnabled = await check(projectId, apiName, prefix, silent);
if (isEnabled) {
void track("api_enabled", apiName);
void trackGA4("api_enabled", {
api_name: apiName,
});
return;
}
if (!silent) {
Expand Down
5 changes: 0 additions & 5 deletions src/extensions/paramHelper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { logger } from "../logger";
import { ExtensionInstance, ExtensionSpec, Param } from "./types";
import { getFirebaseProjectParams, substituteParams } from "./extensionsHelper";
import * as askUserForParam from "./askUserForParam";
import { track } from "../track";
import * as env from "../functions/env";
import { cloneDeep } from "../utils";

Expand Down Expand Up @@ -111,8 +110,6 @@ export async function getParams(args: {
reconfiguring: !!args.reconfiguring,
});
}
const paramNames = Object.keys(params);
void track("Extension Params", paramNames.length ? "Not Present" : "Present", paramNames.length);
return params;
}

Expand All @@ -137,8 +134,6 @@ export async function getParamsForUpdate(args: {
instanceId: args.instanceId,
});
}
const paramNames = Object.keys(params);
void track("Extension Params", paramNames.length ? "Not Present" : "Present", paramNames.length);
return params;
}

Expand Down
8 changes: 6 additions & 2 deletions src/test/deploy/hosting/prepare.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ describe("hosting prepare", () => {
};
await prepare(context, options);

expect(trackingStub.track).to.have.been.calledOnceWith("hosting_deploy", "fake-framework");
expect(trackingStub.trackGA4).to.have.been.calledOnceWith("hosting_version", {
framework: "fake-framework",
});
expect(hostingStub.createVersion).to.have.been.calledOnce;
expect(context.hosting).to.deep.equal({
deploys: [
Expand Down Expand Up @@ -138,7 +140,9 @@ describe("hosting prepare", () => {
};
await prepare(context, options);

expect(trackingStub.track).to.have.been.calledOnceWith("hosting_deploy", "classic");
expect(trackingStub.trackGA4).to.have.been.calledOnceWith("hosting_version", {
framework: "classic",
});
expect(hostingStub.createVersion).to.have.been.calledOnce;
expect(context.hosting).to.deep.equal({
deploys: [
Expand Down
Loading