From 6b373bee473bf26040adf32fe1ba38d7b02ed9e8 Mon Sep 17 00:00:00 2001 From: Andrew Bastin Date: Mon, 5 Jul 2021 12:42:44 -0400 Subject: [PATCH 1/9] feat: update env with FB_MEASUREMENT_ID --- .env.example | 1 + 1 file changed, 1 insertion(+) diff --git a/.env.example b/.env.example index b41817769..fab8d26ec 100644 --- a/.env.example +++ b/.env.example @@ -13,6 +13,7 @@ STORAGE_BUCKET=postwoman-api.appspot.com MESSAGING_SENDER_ID=421993993223 APP_ID=1:421993993223:web:ec0baa8ee8c02ffa1fc6a2 MEASUREMENT_ID=G-ERJ6025CEB +FB_MEASUREMENT_ID=G-BBJ3R80PJT # Base URL BASE_URL=https://hoppscotch.io From b1418c081c682052f85e9ca3fcb004fdef9db7c8 Mon Sep 17 00:00:00 2001 From: Andrew Bastin Date: Mon, 5 Jul 2021 12:44:43 -0400 Subject: [PATCH 2/9] feat: auth event subject --- helpers/fb/auth.ts | 36 +++++++++++++++++++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/helpers/fb/auth.ts b/helpers/fb/auth.ts index 5fa323a45..08a7c0874 100644 --- a/helpers/fb/auth.ts +++ b/helpers/fb/auth.ts @@ -1,11 +1,16 @@ import firebase from "firebase" -import { BehaviorSubject } from "rxjs" +import { BehaviorSubject, Subject } from "rxjs" export type HoppUser = firebase.User & { provider?: string accessToken?: string } +type AuthEvents = + | { event: "login"; user: HoppUser } + | { event: "logout" } + | { event: "authTokenUpdate"; user: HoppUser; newToken: string | null } + /** * A BehaviorSubject emitting the currently logged in user (or null if not logged in) */ @@ -15,6 +20,11 @@ export const currentUser$ = new BehaviorSubject(null) */ export const authIdToken$ = new BehaviorSubject(null) +/** + * A subject that emits events related to authentication flows + */ +export const authEvents$ = new Subject() + /** * Initializes the firebase authentication related subjects */ @@ -22,6 +32,9 @@ export function initAuth() { let extraSnapshotStop: (() => void) | null = null firebase.auth().onAuthStateChanged((user) => { + /** Whether the user was logged in before */ + const wasLoggedIn = currentUser$.value !== null + if (!user && extraSnapshotStop) { extraSnapshotStop() extraSnapshotStop = null @@ -61,14 +74,35 @@ export function initAuth() { userUpdate.provider = data.provider userUpdate.accessToken = data.accessToken } + + currentUser$.next(userUpdate) }) } currentUser$.next(user) + + // User wasn't found before, but now is there (login happened) + if (!wasLoggedIn && user) { + authEvents$.next({ + event: "login", + user: currentUser$.value!!, + }) + } else if (wasLoggedIn && !user) { + // User was found before, but now is not there (logout happened) + authEvents$.next({ + event: "logout", + }) + } }) firebase.auth().onIdTokenChanged(async (user) => { if (user) { authIdToken$.next(await user.getIdToken()) + + authEvents$.next({ + event: "authTokenUpdate", + newToken: authIdToken$.value, + user: currentUser$.value!!, // Force not-null because user is defined + }) } else { authIdToken$.next(null) } From 913b073ba423eada2b9322bfb81f3d175d20560d Mon Sep 17 00:00:00 2001 From: Andrew Bastin Date: Mon, 5 Jul 2021 12:45:10 -0400 Subject: [PATCH 3/9] feat: add initial analytics implementation --- helpers/fb/analytics.ts | 48 +++++++++++++++++++++++++++++++++++++++++ helpers/fb/index.ts | 25 +++++++++++++-------- 2 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 helpers/fb/analytics.ts diff --git a/helpers/fb/analytics.ts b/helpers/fb/analytics.ts new file mode 100644 index 000000000..839b1448d --- /dev/null +++ b/helpers/fb/analytics.ts @@ -0,0 +1,48 @@ +import firebase from "firebase" +import { authEvents$ } from "./auth" +import { settings$ } from "~/newstore/settings" + +let analytics: firebase.analytics.Analytics + +type SettingsCustomDimensions = { + usesProxy: boolean + usesExtension: boolean + usesScrollInto: boolean + syncCollections: boolean + syncEnvironments: boolean + syncHistory: boolean +} + +export function initAnalytics() { + analytics = firebase.app().analytics() + + initLoginListeners() + initSettingsListeners() +} + +function initLoginListeners() { + authEvents$.subscribe((ev) => { + if (ev.event === "login") { + analytics.setUserId(ev.user.uid) + + analytics.logEvent("login", { + method: ev.user.providerData[0]?.providerId, // Assume the first provider is the login provider + }) + } else if (ev.event === "logout") { + analytics.logEvent("logout") + } + }) +} + +function initSettingsListeners() { + settings$.subscribe((settings) => { + analytics.setUserProperties({ + usesProxy: settings.PROXY_ENABLED, + usesExtension: settings.EXTENSIONS_ENABLED, + usesScrollInto: settings.SCROLL_INTO_ENABLED, + syncCollections: settings.syncCollections, + syncEnvironments: settings.syncEnvironments, + syncHistory: settings.syncHistory, + }) + }) +} diff --git a/helpers/fb/index.ts b/helpers/fb/index.ts index 25566d530..9eb128b11 100644 --- a/helpers/fb/index.ts +++ b/helpers/fb/index.ts @@ -1,4 +1,5 @@ import firebase from "firebase" +import { initAnalytics } from "./analytics" import { initAuth } from "./auth" import { initCollections } from "./collections" import { initEnvironments } from "./environments" @@ -13,21 +14,27 @@ const firebaseConfig = { storageBucket: process.env.STORAGE_BUCKET, messagingSenderId: process.env.MESSAGING_SENDER_ID, appId: process.env.APP_ID, - measurementId: process.env.MEASUREMENT_ID, + measurementId: process.env.FB_MEASUREMENT_ID, } let initialized = false export function initializeFirebase() { if (!initialized) { - firebase.initializeApp(firebaseConfig) + try { + firebase.initializeApp(firebaseConfig) - initAuth() - initSettings() - initCollections() - initHistory() - initEnvironments() + initAuth() + initSettings() + initCollections() + initHistory() + initEnvironments() + initAnalytics() - initialized = true + initialized = true + } catch (e) { + // initializeApp throws exception if we reinitialize + initialized = true + } } -} +} \ No newline at end of file From 86bd4aa568c3b2cd86176df3d00270059040260b Mon Sep 17 00:00:00 2001 From: Andrew Bastin Date: Mon, 5 Jul 2021 20:02:29 -0400 Subject: [PATCH 4/9] feat: add analytics logging while hoppscotch requests are fired --- components/realtime/Mqtt.vue | 5 +++++ components/realtime/Socketio.vue | 5 +++++ components/realtime/Sse.vue | 5 +++++ components/realtime/Websocket.vue | 5 +++++ helpers/fb/analytics.ts | 11 +++++++++++ helpers/network.js | 16 ++++++++++++++++ pages/graphql.vue | 13 ++++++++++++- pages/index.vue | 12 +++++++++++- 8 files changed, 70 insertions(+), 2 deletions(-) diff --git a/components/realtime/Mqtt.vue b/components/realtime/Mqtt.vue index 189cd0c98..0ff047bf1 100644 --- a/components/realtime/Mqtt.vue +++ b/components/realtime/Mqtt.vue @@ -121,6 +121,7 @@ diff --git a/components/smart/ColorModePicker.vue b/components/smart/ColorModePicker.vue index 52b236743..34843942a 100644 --- a/components/smart/ColorModePicker.vue +++ b/components/smart/ColorModePicker.vue @@ -3,11 +3,8 @@