openpanel service hinzugefügt
This commit is contained in:
@@ -1,29 +1,148 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Injectable, OnDestroy, inject } from '@angular/core';
|
||||
import { Router, NavigationEnd } from '@angular/router';
|
||||
import { isPlatformBrowser } from '@angular/common';
|
||||
import { PLATFORM_ID } from '@angular/core';
|
||||
import { filter, Subscription, skip } from 'rxjs';
|
||||
import { OpenPanel } from '@openpanel/web';
|
||||
import type { IdentifyPayload } from '@openpanel/web';
|
||||
import { OpenPanelConfig, OPENPANEL_CONFIG } from '@core/models/openpanel.model';
|
||||
|
||||
export type TrackProperties = Record<string, string | number | boolean | null | undefined>;
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
providedIn: 'root',
|
||||
})
|
||||
export class AnalyticsService {
|
||||
private openpanel: OpenPanel;
|
||||
export class OpenPanelService implements OnDestroy {
|
||||
private readonly config = inject(OPENPANEL_CONFIG);
|
||||
private readonly platformId = inject(PLATFORM_ID)
|
||||
private readonly router = inject(Router);
|
||||
|
||||
private op?: OpenPanel;
|
||||
private routerSubscription?: Subscription;
|
||||
|
||||
constructor() {
|
||||
this.openpanel = new OpenPanel({
|
||||
clientId: 'DEINE_CLIENT_ID',
|
||||
trackScreenViews: true,
|
||||
trackOutgoingLinks: true,
|
||||
});
|
||||
}
|
||||
|
||||
trackEvent(name: string, properties?: Record<string, any>) {
|
||||
this.openpanel.track(name, properties);
|
||||
}
|
||||
|
||||
identifyUser(userId: string, traits?: Record<string, any>) {
|
||||
this.openpanel.identify(userId);
|
||||
|
||||
if (traits) {
|
||||
this.openpanel.setProfile(traits);
|
||||
if(isPlatformBrowser(this.platformId)) {
|
||||
this.initialize();
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Initialization ────────────────────────────────────────────────────────
|
||||
|
||||
private initialize(): void {
|
||||
this.op = new OpenPanel({
|
||||
clientId: this.config.clientId,
|
||||
apiUrl: this.config.apiUrl,
|
||||
trackScreenViews: false, // We handle this manually via Router
|
||||
trackOutgoingLinks: this.config.trackOutgoingLinks ?? false,
|
||||
trackAttributes: this.config.trackAttributes ?? false,
|
||||
disabled: this.config.disabled ?? false,
|
||||
});
|
||||
|
||||
if (this.config.globalProperties) {
|
||||
this.op.setGlobalProperties(this.config.globalProperties);
|
||||
}
|
||||
|
||||
if (this.config.trackScreenViews !== false) {
|
||||
this.setupRouteTracking();
|
||||
}
|
||||
}
|
||||
|
||||
private setupRouteTracking(): void {
|
||||
// Nur einmalig subscriben, vorherige Sub zerstören
|
||||
this.routerSubscription?.unsubscribe();
|
||||
|
||||
this.routerSubscription = this.router.events
|
||||
.pipe(
|
||||
filter((event) => event instanceof NavigationEnd),
|
||||
// Ersten initialNavigation-Event überspringen – SSR hat ihn schon getriggert
|
||||
skip(1),
|
||||
)
|
||||
.subscribe((event) => {
|
||||
const navEvent = event as NavigationEnd;
|
||||
this.trackScreenView(navEvent.urlAfterRedirects);
|
||||
});
|
||||
}
|
||||
|
||||
// ─── Public API ────────────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* Tracks a custom event with optional properties.
|
||||
* @example opService.track('button_clicked', { button_name: 'signup' });
|
||||
*/
|
||||
track(eventName: string, properties?: TrackProperties): void {
|
||||
if (!this.op) return;
|
||||
if (this.config.debug) {
|
||||
console.debug('[OpenPanel] track:', eventName, properties);
|
||||
}
|
||||
this.op.track(eventName, properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Identifies the current user. Call this after login.
|
||||
* @example opService.identify({ profileId: 'user-123', email: 'user@example.com' });
|
||||
*/
|
||||
identify(payload: IdentifyPayload): void {
|
||||
if (!this.op) return;
|
||||
if (this.config.debug) {
|
||||
console.debug('[OpenPanel] identify:', payload.profileId);
|
||||
}
|
||||
this.op.identify(payload);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the current user identity. Call this on logout.
|
||||
*/
|
||||
clearUser(): void {
|
||||
if (!this.op) return;
|
||||
if (this.config.debug) {
|
||||
console.debug('[OpenPanel] clearUser');
|
||||
}
|
||||
this.op.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets properties that will be sent with every subsequent event.
|
||||
*/
|
||||
setGlobalProperties(properties: TrackProperties): void {
|
||||
if (!this.op) return;
|
||||
this.op.setGlobalProperties(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments a numeric property on the user profile.
|
||||
* @example opService.increment('login_count');
|
||||
*/
|
||||
increment(property: string): void {
|
||||
if (!this.op) return;
|
||||
this.op.increment(property);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Decrements a numeric property on the user profile.
|
||||
* @example opService.decrement('credits', 5);
|
||||
*/
|
||||
decrement(property: string): void {
|
||||
if (!this.op) return;
|
||||
this.op.decrement(property);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manually tracks a screen/page view.
|
||||
*/
|
||||
trackScreenView(path?: string): void {
|
||||
if (!this.op) return;
|
||||
const currentPath = path ?? this.router.url;
|
||||
if (this.config.debug) {
|
||||
console.debug('[OpenPanel] screenView:', currentPath);
|
||||
}
|
||||
this.op.track('screen_view', { path: currentPath });
|
||||
}
|
||||
|
||||
// ─── Cleanup ───────────────────────────────────────────────────────────────
|
||||
|
||||
ngOnDestroy(): void {
|
||||
this.routerSubscription?.unsubscribe();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user