mirror of
https://github.com/bitwarden/browser
synced 2026-02-12 06:23:38 +00:00
feat: add analytics service & directive
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
import { DOCUMENT } from "@angular/common";
|
||||
import { Component, Inject, NgZone, OnDestroy, OnInit } from "@angular/core";
|
||||
import { Component, inject, Inject, NgZone, OnDestroy, OnInit } from "@angular/core";
|
||||
import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
|
||||
import { NavigationEnd, Router } from "@angular/router";
|
||||
import * as jq from "jquery";
|
||||
import { Subject, filter, firstValueFrom, map, takeUntil, timeout, catchError, of } from "rxjs";
|
||||
|
||||
import { CollectionService } from "@bitwarden/admin-console/common";
|
||||
import { AnalyticsService } from "@bitwarden/angular/analytics/analytics.service";
|
||||
import { EventUploadService } from "@bitwarden/common/abstractions/event/event-upload.service";
|
||||
import { NotificationsService } from "@bitwarden/common/abstractions/notifications.service";
|
||||
import { SearchService } from "@bitwarden/common/abstractions/search.service";
|
||||
@@ -60,6 +61,8 @@ export class AppComponent implements OnDestroy, OnInit {
|
||||
private isIdle = false;
|
||||
private destroy$ = new Subject<void>();
|
||||
|
||||
private analyticsService = inject(AnalyticsService);
|
||||
|
||||
loading = false;
|
||||
|
||||
constructor(
|
||||
@@ -267,6 +270,8 @@ export class AppComponent implements OnDestroy, OnInit {
|
||||
new DisableSendPolicy(),
|
||||
new SendOptionsPolicy(),
|
||||
]);
|
||||
|
||||
void this.analyticsService.init();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
|
||||
@@ -299,6 +299,8 @@ const devServer =
|
||||
https://api.fastmail.com
|
||||
https://api.forwardemail.net
|
||||
http://localhost:5000
|
||||
https://plausible.io/api/event
|
||||
|
||||
;object-src
|
||||
'self'
|
||||
blob:
|
||||
|
||||
48
libs/angular/src/analytics/analytics.service.ts
Normal file
48
libs/angular/src/analytics/analytics.service.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { inject, Injectable } from "@angular/core";
|
||||
import Plausible from "plausible-tracker";
|
||||
// import { firstValueFrom } from "rxjs";
|
||||
|
||||
import { ANALYTICS, GlobalStateProvider, KeyDefinition } from "@bitwarden/common/platform/state";
|
||||
|
||||
const ANALYTICS_ENABLED_KEY_DEF = new KeyDefinition<boolean>(ANALYTICS, "analytics_enabled", {
|
||||
deserializer: (s) => s,
|
||||
});
|
||||
|
||||
@Injectable({ providedIn: "root" })
|
||||
export class AnalyticsService {
|
||||
private plausible: ReturnType<typeof Plausible>;
|
||||
private plausibleCleanup?: () => any;
|
||||
|
||||
private readonly _enabledState = inject(GlobalStateProvider).get(ANALYTICS_ENABLED_KEY_DEF);
|
||||
readonly enabled$ = this._enabledState.state$;
|
||||
|
||||
async init() {
|
||||
this.plausible = Plausible({
|
||||
domain: "bitwarden",
|
||||
trackLocalhost: true,
|
||||
hashMode: true,
|
||||
});
|
||||
|
||||
// TODO: uncomment when a toggle is added to settings page
|
||||
// const enabled = await firstValueFrom(this._enabledState.state$);
|
||||
// if (!enabled) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
await this.enable();
|
||||
}
|
||||
|
||||
async enable() {
|
||||
await this._enabledState.update((_prevState) => true);
|
||||
this.plausibleCleanup = this.plausible.enableAutoPageviews();
|
||||
}
|
||||
|
||||
async disable() {
|
||||
await this._enabledState.update((_prevState) => false);
|
||||
this?.plausibleCleanup();
|
||||
}
|
||||
|
||||
trackEvent(eventName: string) {
|
||||
this.plausible.trackEvent(eventName);
|
||||
}
|
||||
}
|
||||
22
libs/angular/src/analytics/track-event.directive.ts
Normal file
22
libs/angular/src/analytics/track-event.directive.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { Directive, HostListener, inject, Input } from "@angular/core";
|
||||
|
||||
import { AnalyticsService } from "./analytics.service";
|
||||
|
||||
@Directive({
|
||||
selector: "[track-event]",
|
||||
standalone: true,
|
||||
})
|
||||
export class TrackEventDirective {
|
||||
private analyticsService = inject(AnalyticsService);
|
||||
|
||||
@Input({
|
||||
alias: "track-event",
|
||||
required: true,
|
||||
})
|
||||
eventName!: string;
|
||||
|
||||
@HostListener("click")
|
||||
handleClick() {
|
||||
this.analyticsService.trackEvent(this.eventName);
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import {
|
||||
TypographyModule,
|
||||
} from "@bitwarden/components";
|
||||
|
||||
import { TrackEventDirective } from "./analytics/track-event.directive";
|
||||
import { TwoFactorIconComponent } from "./auth/components/two-factor-icon.component";
|
||||
import { DeprecatedCalloutComponent } from "./components/callout.component";
|
||||
import { A11yInvalidDirective } from "./directives/a11y-invalid.directive";
|
||||
@@ -81,6 +82,7 @@ import { IconComponent } from "./vault/components/icon.component";
|
||||
IconModule,
|
||||
LinkModule,
|
||||
IconModule,
|
||||
TrackEventDirective,
|
||||
],
|
||||
declarations: [
|
||||
A11yInvalidDirective,
|
||||
|
||||
@@ -124,6 +124,7 @@ export const TASK_SCHEDULER_DISK = new StateDefinition("taskScheduler", "disk");
|
||||
// Design System
|
||||
|
||||
export const POPUP_STYLE_DISK = new StateDefinition("popupStyle", "disk");
|
||||
export const ANALYTICS = new StateDefinition("analytics", "disk");
|
||||
|
||||
// Secrets Manager
|
||||
|
||||
|
||||
9
package-lock.json
generated
9
package-lock.json
generated
@@ -62,6 +62,7 @@
|
||||
"open": "8.4.2",
|
||||
"papaparse": "5.4.1",
|
||||
"patch-package": "8.0.0",
|
||||
"plausible-tracker": "^0.3.9",
|
||||
"popper.js": "1.16.1",
|
||||
"proper-lockfile": "4.1.2",
|
||||
"qrcode-parser": "2.1.3",
|
||||
@@ -27174,6 +27175,14 @@
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/plausible-tracker": {
|
||||
"version": "0.3.9",
|
||||
"resolved": "https://registry.npmjs.org/plausible-tracker/-/plausible-tracker-0.3.9.tgz",
|
||||
"integrity": "sha512-hMhneYm3GCPyQon88SZrVJx+LlqhM1kZFQbuAgXPoh/Az2YvO1B6bitT9qlhpiTdJlsT5lsr3gPmzoVjb5CDXA==",
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/plist": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/plist/-/plist-3.1.0.tgz",
|
||||
|
||||
@@ -191,6 +191,7 @@
|
||||
"open": "8.4.2",
|
||||
"papaparse": "5.4.1",
|
||||
"patch-package": "8.0.0",
|
||||
"plausible-tracker": "^0.3.9",
|
||||
"popper.js": "1.16.1",
|
||||
"proper-lockfile": "4.1.2",
|
||||
"qrcode-parser": "2.1.3",
|
||||
|
||||
Reference in New Issue
Block a user