angular - 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);
}),
);
}
}
调用的主要函数AppComponent
是init
. 这会将脚本注入页面。当我观察应用程序加载时,我看到这些脚本被添加了。我还在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
.
有没有办法解决这个问题?我在这里做错了什么吗?任何想法都非常感谢。
解决方案
所以事实证明,在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
我以前得到的。
推荐阅读
- unreal-engine4 - 如何在虚幻引擎 4 中设置屏幕分辨率?
- php - 更改产品数量栏
- javascript - 使用 redux 工具包在反应功能组件上显示模态
- javascript - D3根据数据更新颜色
- javascript - Django:警告框显示值的Javascript错误
- xcode - Xcode 12.3 iOS 14.3 模拟器 Yellow Dock / 黄色半透明问题
- python - 如何阻止 pybind11 释放由 Python 构造的对象?
- javascript - 如何从初始状态中选择特定值?反应 - Redux
- javascript - 在Angular中加载组件时防止无线电值更改时出错
- docker - 无法启动 docker-deploy-hdp30.sh 并出现错误:没有这样的容器:sandbox-hdp