Angular9通过angular-google-tag-manager接入GTM异步获取ID报错问题
问题根因
你的工厂函数返回的是subscribe()调用产生的Subscription订阅对象,不是GTM的ID字符串,angular-google-tag-manager库直接把你返回的对象转成字符串拼到请求地址里,才会出现id=[object%20Object]的404错误。另外Angular的普通useFactory默认不支持异步返回结果,就算直接返回Observable/Promise也无法被库正确识别为ID值。
解决方法
方法1:用APP_INITIALIZER提前加载GTM ID(推荐)
在应用启动前先拉取到GTM ID,再注入给GTM库,兼容性最好。
- 先修改工厂函数,把拉取GTM ID的逻辑封装成APP_INITIALIZER可识别的Promise形式:
import { ApiService } from '../api.service'; // 存储加载完成的GTM ID let gtmContainerId: string; export const loadGtmIdFactory = (apiService: ApiService) => { return () => apiService.getUserInfo().toPromise().then(apiResponse => { gtmContainerId = apiResponse.googleTagManagerContainerID; return gtmContainerId; }); }; export const getGtmId = () => gtmContainerId;
- 修改app.module.ts的配置,确保先加载GTM ID再初始化GTM库:
import { APP_INITIALIZER, NgModule } from '@angular/core'; import { GoogleTagManagerModule } from 'angular-google-tag-manager'; @NgModule({ imports: [ // 不要在forRoot传固定ID,后续动态注入 GoogleTagManagerModule.forRoot() ], providers: [ { provide: APP_INITIALIZER, useFactory: loadGtmIdFactory, deps: [ApiService], multi: true }, { provide: 'googleTagManagerId', useFactory: getGtmId } ] }) export class AppModule { }
方法2:手动初始化GTM(不阻塞应用启动)
如果不想让接口请求阻塞首屏加载,可以关闭库的自动初始化,拿到ID后手动触发初始化:
- app.module.ts引入GTM模块时关闭自动初始化:
GoogleTagManagerModule.forRoot({ id: null, isAutoInit: false })
- 在业务逻辑里拿到ID后手动触发GTM加载:
import { GoogleTagManagerService } from 'angular-google-tag-manager'; constructor( private apiService: ApiService, private gtmService: GoogleTagManagerService ) {} ngOnInit() { this.apiService.getUserInfo().subscribe(res => { const gtmId = res.googleTagManagerContainerID; // 手动将GTM脚本插入到页面 this.gtmService.addGtmToDom(gtmId); }); }
内容的提问来源于stack exchange,提问作者Marek
相关产品推荐
相关产品推荐

