首页 > 解决方案 > Angular 和谷歌分析

问题描述

我正在尝试将 Google Analytics 添加到我的 Angular 应用程序中,而无需手动将脚本添加到索引文件中。我的目标是使用具有您可以调用的功能的服务来初始化分析和跟踪页面浏览量。这是服务的主要部分:

export class GoogleAnalyticsService {
    private googleAnalyticsId: string;
    private renderer2: Renderer2;
    private scriptsLoaded: boolean = false;

    constructor(
        private rendererFactory2: RendererFactory2,
        @Inject(DOCUMENT) private _document: Document,
        private _config: RuntimeConfigLoaderService,
        private _router: Router,
    ) {
        this.renderer2 = this.rendererFactory2.createRenderer(null, null);
        this.googleAnalyticsId = this._config.getConfigObjectKey('googleAnalyticsId');
    }

    init() {
        this.insertMainScript();
    }

    private insertMainScript() {
        if (this.googleAnalyticsId) {
            const script: HTMLScriptElement = this.renderer2.createElement('script');
            script.type = 'text/javascript';
            script.onload = this.insertSecondHalfOfScript.bind(this);
            script.src = `https://www.googletagmanager.com/gtag/js?id=${this.googleAnalyticsId}`;
            script.text = '';
            this.renderer2.appendChild(this._document.body, script);
        }
    }

    private insertSecondHalfOfScript() {
        const script: HTMLScriptElement = this.renderer2.createElement('script');
        script.type = 'text/javascript';
        script.src = '';
        script.text = `
            window.dataLayer = window.dataLayer || [];
            function gtag(){dataLayer.push(arguments);}
            gtag('js', new Date());
        `;
        this.renderer2.appendChild(this._document.body, script);
        this.scriptsLoaded = true;
    }

    trackSinglePageView(event: NavigationEnd) {
        if (this.googleAnalyticsId && this.scriptsLoaded) {
            console.log('logging pageview');
            gtag('config', this.googleAnalyticsId, { page_path: event.urlAfterRedirects });
        }
    }

    trackPageViews() {
        return this._router.events.pipe(
            filter((evt: RouterEvent) => evt instanceof NavigationEnd),
            tap((event: NavigationEnd) => {
                this.trackSinglePageView(event);
            }),
        );
    }
}

调用的主要函数AppComponentinit. 这会将脚本注入页面。当我观察应用程序加载时,我看到这些脚本被添加了。我还在https://www.googletagmanager.com/gtag/js开发人员工具的“网络”选项卡中看到了脚本加载。所以剧本肯定在那里。

然后在调用init函数后AppComponent我调用trackPageViews函数并订阅返回的 Observable。我过滤掉所有的路由器事件,直到上面的脚本被加载,然后过滤掉所有不是事件的NavigationEnd事件。如果脚本已加载并且它是 NavigationEnd 事件,则使用必要的数据调用该trackSinglePageView函数。gtag但是,发生这种情况时,我收到以下错误:

core.js:6189 ERROR ReferenceError: gtag is not defined
    at GoogleAnalyticsService.trackSinglePageView (google-analytics.service.ts:58)
    at TapSubscriber._tapNext (google-analytics.service.ts:69)
    at TapSubscriber._next (tap.js:40)
    at TapSubscriber.next (Subscriber.js:49)
    at FilterSubscriber._next (filter.js:33)
    at FilterSubscriber.next (Subscriber.js:49)
    at Subject.next (Subject.js:39)
    at SafeSubscriber._next (router.js:7593)
    at SafeSubscriber.__tryOrUnsub (Subscriber.js:183)
    at SafeSubscriber.next (Subscriber.js:122)

如果我不使用该服务加载分析脚本并将它们放在head应用程序的 index.html 文件中并仅跟踪页面视图,那么我不会在控制台中收到任何错误。因此,尽管脚本已加载,gtag但除非分析脚本位于head.

有没有办法解决这个问题?我在这里做错了什么吗?任何想法都非常感谢。

标签: angulartypescript

解决方案


所以事实证明,在insertSecondHalfOfScript函数中创建的脚本文本从未运行过。看起来这gtag就是页面可用的地方。因此,我没有将代码添加到该文本属性,而是将其放入资产文件中并像在insertMainScript函数中加载脚本一样加载它。所以启动流程现在看起来像这样:

init() {
    this.insertMainScript();
}

private insertMainScript() {
    if (this.googleAnalyticsId) {
        const script: HTMLScriptElement = this.renderer2.createElement('script');
        script.type = 'text/javascript';
        script.onload = this.insertSecondHalfOfScript.bind(this);
        script.src = `https://www.googletagmanager.com/gtag/js?id=${this.googleAnalyticsId}`;
        script.text = '';
        this.renderer2.appendChild(this._document.body, script);
    }
}

private insertSecondHalfOfScript() {
    const script: HTMLScriptElement = this.renderer2.createElement('script');
    script.type = 'text/javascript';
    script.src = '/assets/scripts/analytics/analytics-starting-script.js';
    script.text = '';
    this.renderer2.appendChild(this._document.body, script);
    script.onload = () => {
        this.scriptsLoaded = true;
    };
}

像这样加载第二个脚本似乎可行,因为我现在没有得到ReferenceError我以前得到的。


推荐阅读