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

feat: track custom analytics events #243

Merged
merged 12 commits into from
Feb 29, 2024
5 changes: 2 additions & 3 deletions apps/picsa-apps/extension-app/src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ export class AppComponent {
private async init() {
this.performanceService.setEnabled({ enabled: ENVIRONMENT.production });
this.crashlyticsService.ready().then(() => null);
if (ENVIRONMENT.production) {
this.analyticsService.init(this.router);
}
// eagerly enable analytics collection
this.analyticsService.init(this.router);
// eagerly load resources service to populate hardcoded resources
this.resourcesService.ready();
// eagerly load monitoring service to sync form data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
[style.display]="videoUri ? 'none' : 'block'"
></resource-item-file>
<h2 *ngIf="videoUri">{{ videoResource.title | translate }}</h2>
<picsa-video-player #videoPlayer *ngIf="videoUri" [source]="videoUri"></picsa-video-player>
<picsa-video-player #videoPlayer *ngIf="videoUri" [id]="videoResource.id" [source]="videoUri"></picsa-video-player>
<p>
{{ 'In this video you will learn about the PICSA step:' | translate }}
{{ activity!.label | translate }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,6 @@ export class ResourceItemFileComponent implements OnInit, OnDestroy {

/** Generic file opener */
public async handleFileLinkClick(e: Event) {
this.service.openFileResource(this.fileURI, this.attachment!.type);
this.service.openFileResource(this.fileURI, this.attachment!.type, this.resource.id);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import { IResourceFile } from '../../schemas';
selector: 'resource-item-video',
template: `
<h2>{{ resource.title | translate }}</h2>
<picsa-video-player [source]="fileURI" #videoPlayer [thumbnail]="resource.cover?.image"> </picsa-video-player>
<picsa-video-player [source]="fileURI" #videoPlayer [thumbnail]="resource.cover?.image" [id]="resource.id">
</picsa-video-player>
<p *ngIf="resource.description">{{ resource.description | translate }}</p>
`,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { Capacitor } from '@capacitor/core';
import { ConfigurationService } from '@picsa/configuration/src';
import { APP_VERSION } from '@picsa/environments/src';
import { PicsaAsyncService } from '@picsa/shared/services/asyncService.service';
import { AnalyticsService } from '@picsa/shared/services/core/analytics.service';
import { PicsaDatabase_V2_Service, PicsaDatabaseAttachmentService } from '@picsa/shared/services/core/db_v2';
import { FileService } from '@picsa/shared/services/core/file.service';
import { NativeStorageService } from '@picsa/shared/services/native';
Expand All @@ -21,7 +22,8 @@ export class ResourcesToolService extends PicsaAsyncService {
private dbAttachmentService: PicsaDatabaseAttachmentService,
private configurationService: ConfigurationService,
private nativeStorageService: NativeStorageService,
private fileService: FileService
private fileService: FileService,
private analyticsService: AnalyticsService
) {
super();
}
Expand Down Expand Up @@ -70,7 +72,9 @@ export class ResourcesToolService extends PicsaAsyncService {
});
}

public async openFileResource(uri: string, mimetype: string) {
public async openFileResource(uri: string, mimetype: string, id: string) {
// track the resource open event
this.analyticsService.trackResourceOpen(id);
if (Capacitor.isNativePlatform()) {
try {
this.nativeStorageService.openFileURI(uri, mimetype);
Expand Down
19 changes: 17 additions & 2 deletions libs/shared/src/features/video-player/video-player.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import { Capacitor } from '@capacitor/core';
import { ScreenOrientation } from '@capacitor/screen-orientation';
import { CapacitorVideoPlayer, CapacitorVideoPlayerPlugin, capVideoPlayerOptions } from 'capacitor-video-player';

import { AnalyticsService } from '../../services/core/analytics.service';

// Fix listeners missing from type
// https://github.com/jepiqueau/capacitor-video-player/blob/master/docs/API.md#listeners
type IVideoEvent =
Expand All @@ -28,16 +30,27 @@ interface IVideoPlayer extends CapacitorVideoPlayerPlugin {
export class VideoPlayerComponent implements OnDestroy {
/** Optional override of player options */
@Input() options: Partial<capVideoPlayerOptions> = {};

/** Unique video id, used for analytics and handling multiple videos */
@Input() id: string;

/** Video source - can be string url or data blob */
@Input() source?: string;

/** Optional image shown as preview */
@Input() thumbnail?: string;

/** Specify whether should open overlay to play video (default inline) */
@Input() playInModal = false;

// Bind player id to host element to support element query when initialising player
@HostBinding('attr.data-player-id') playerId = `videoPlayer_${generateID(5)}`;
@HostBinding('attr.data-player-id') get playerId() {
if (!this.id) {
console.warn('No id provided to <picsa-video-player> component');
this.id = `videoPlayer_${generateID(5)}`;
}
return this.id;
}

protected showPlayButton = true;

Expand All @@ -53,7 +66,7 @@ export class VideoPlayerComponent implements OnDestroy {

private pauseTime: number = 0;

constructor(private elementRef: ElementRef<HTMLDivElement>) {}
constructor(private elementRef: ElementRef<HTMLDivElement>, private analyticsService: AnalyticsService) {}

async ngOnDestroy() {
await this.videoPlayer.stopAllPlayers();
Expand All @@ -74,6 +87,8 @@ export class VideoPlayerComponent implements OnDestroy {
if (Capacitor.isNativePlatform()) {
this.initialised = false;
}
// Track video play event
this.analyticsService.trackVideoPlay(this.playerId);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit(non-blocking): currently the playerId is a randomly generated id, so it doesn't really hold any analytics value. It might be good to implement player IDs as suggested in #241 (but not the full storage solution) so that we can track the id of the resource when passed to the video player and for logging in analytics

This could either be included in this pr (would only be a few lines of code), or as part of a follow-up

// Initialise player any time playback triggered in case url updated (e.g. downloaded after init)
await this.initPlayer();
this.videoPlayer.play({ playerId: this.playerId }).then(() => {
Expand Down
28 changes: 23 additions & 5 deletions libs/shared/src/services/core/analytics.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Injectable } from '@angular/core';
import { NavigationEnd,Router } from '@angular/router';
import { NavigationEnd, Router } from '@angular/router';
import { Capacitor } from '@capacitor/core';
import { FirebaseAnalytics } from '@capacitor-community/firebase-analytics';
import { APP_VERSION,ENVIRONMENT } from '@picsa/environments';
import { APP_VERSION, ENVIRONMENT } from '@picsa/environments';

@Injectable({ providedIn: 'root' })
/**
Expand All @@ -12,11 +12,13 @@ import { APP_VERSION,ENVIRONMENT } from '@picsa/environments';
export class AnalyticsService {
public firebaseAnalytics = FirebaseAnalytics;

public init(router: Router) {
public async init(router: Router) {
if (!Capacitor.isNativePlatform()) {
// initialise for web (not required on android)
FirebaseAnalytics.initializeFirebase(ENVIRONMENT.firebase);
await FirebaseAnalytics.initializeFirebase(ENVIRONMENT.firebase);
}
// disable analytics collection when running in dev
await this.firebaseAnalytics.setCollectionEnabled({ enabled: ENVIRONMENT.production });
this.trackScreenView(router);
}
/**
Expand All @@ -29,10 +31,26 @@ export class AnalyticsService {
if (e instanceof NavigationEnd) {
this.firebaseAnalytics.setScreenName({ screenName: location.pathname });
this.firebaseAnalytics.logEvent({
name: 'screen_view',
name: 'picsa_screen_view',
params: { screen_name: location.pathname, app_version: APP_VERSION },
});
}
});
}

// Method to track when users play a video
public trackVideoPlay(videoId: string) {
this.firebaseAnalytics.logEvent({
name: 'picsa_video_play',
params: { video_id: videoId },
});
}

// Method to track when users opens resource file
public trackResourceOpen(resourceId: string) {
this.firebaseAnalytics.logEvent({
name: 'picsa_resource_open',
params: { resource_id: resourceId },
});
}
}
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -15147,7 +15147,7 @@ __metadata:
"leaflet-draw@github:enketo/Leaflet.draw#ff730785db7fcccbf2485ffcf4dffe1238a7c617":
version: 1.0.4
resolution: "leaflet-draw@https://github.com/enketo/Leaflet.draw.git#commit=ff730785db7fcccbf2485ffcf4dffe1238a7c617"
checksum: b08b88994769667f11f2b6a8937656c89cea34dafd4661abab0b48b4b97f3bddbdce7b23ddfdb8d7c6335e065530e32a70e281314afa34afa134bf68597945fc
checksum: ff548d48c7562be501934f81303061204450e037005ef08591049951adb3044778a6e9c97daa6bac57827ce8864d4637046a8a5669fab5ab43feec7bb3bed86f
languageName: node
linkType: hard

Expand Down
Loading