Last active
December 15, 2023 08:45
-
-
Save max-lt/2cf14e53ad479eaaa7b416223d195868 to your computer and use it in GitHub Desktop.
Angular + Piano Analytics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@angular/core'; | |
import { NavigationEnd, Router } from '@angular/router'; | |
import { filter, map } from 'rxjs/operators'; | |
import { logger } from '~/logger'; | |
import { Config } from '~/config'; | |
const log = logger.getLogger('AnalyticsService'); | |
// Global variables used by piano analytics | |
declare global { | |
interface Window { | |
_pac: any; | |
_paqueue: any[]; | |
} | |
} | |
interface IPianoConfig { | |
site: number | string; | |
collectDomain: string; | |
} | |
@Injectable({ providedIn: 'root' }) | |
export class AnalyticsService { | |
constructor(router: Router, globalConfig: Config) { | |
log.debug(`Init Analytics service on ${router.routerState}`); | |
// Check piano analytics configuration | |
const config: IPianoConfig = globalConfig.getPianoAnalyticsConfig(); | |
if (!config.site || !config.collectDomain) { | |
log.warn('Missing piano analytics configuration'); | |
return; | |
} | |
// Inject piano analytics script asynchronously | |
const script = document.createElement('script'); | |
script.src = 'https://tag.aticdn.net/js-sdk/piano-analytics-6.13.0.js'; | |
script.type = 'text/javascript'; | |
script.async = true; | |
script.crossOrigin = 'anonymous'; | |
script.integrity = 'sha384-hZSi/V4z1wvN+Z/idXMbMuZ9zVoqApJTwCXGxajicf3LI4kEF51eH1c/38wV6Dln'; | |
document.head.appendChild(script); | |
// Init piano analytics context | |
window._pac = window._pac || {}; | |
window._pac.queueVarName = '_paqueue'; | |
// Init piano analytics queue | |
const dataLayer = (window._paqueue = []); | |
// Init piano analytics configuration | |
dataLayer.push(['setConfigurations', config]); | |
// Send page display event on each navigation end | |
router.events | |
.pipe(filter((event): event is NavigationEnd => event instanceof NavigationEnd)) | |
.pipe(map((event) => event.urlAfterRedirects)) | |
.subscribe((page) => dataLayer.push(['sendEvent', 'page.display', { page }])); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ... | |
@NgModule({ | |
// ... | |
providers: [ | |
{ | |
provide: APP_INITIALIZER, | |
useFactory: () => () => {}, | |
deps: [AnalyticsService], | |
multi: true | |
} | |
// ... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Injectable } from '@angular/core'; | |
// Global variables used for config | |
declare global { | |
interface Window { | |
_config: () => IGlobalConfig; | |
} | |
} | |
interface IGlobalConfig { | |
// ... | |
pianoAnalyticsSiteIdentifier: number; | |
pianoAnalyticsCollectDomain: string; | |
} | |
@Injectable({ providedIn: 'root' }) | |
export class Config { | |
private conf: IGlobalConfig; | |
// ... | |
public getPianoAnalyticsConfig() { | |
return { | |
site: this.conf.pianoAnalyticsSiteIdentifier, | |
collectDomain: this.conf.pianoAnalyticsCollectDomain | |
}; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment