You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular中基于Cookie授权的Google Analytics启用/禁用异常问题

Angular集成Google Analytics与Cookie授权问题解决

问题描述

我正尝试在Angular项目中集成Google Analytics与Cookie授权功能,需求为:用户授权后启动Google Analytics追踪,未授权则禁用,默认状态为禁用。

我使用window['ga-disable-${environment.gaTrackingId}'] = false;启用Google Analytics,window['ga-disable-${environment.gaTrackingId}'] = true;禁用它。当前代码可实现默认禁用Google Analytics,但用户点击授权(allow)后,Google Analytics无法启动。

原app.component.ts代码如下:

import {
  Component,
  HostListener,
  OnInit,
  OnDestroy
} from '@angular/core';
import {
  NgcCookieConsentService,
  NgcInitializeEvent,
  NgcNoCookieLawEvent,
  NgcStatusChangeEvent
} from 'ngx-cookieconsent';
import {
  Subscription
} from 'rxjs';
import {
  environment
} from 'src/environments/environment';
import {
  Title
} from '@angular/platform-browser';
import {
  ActivatedRoute
} from '@angular/router';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})

export class AppComponent implements OnInit, OnDestroy {
  isShow ? : boolean;
  topPosToStartShowing = 100;
  public consent!: string;
  notTrackScript!: any;
  trackScript!: any;


  //keep refs to subscriptions to be able to unsubscribe later
  private popupOpenSubscription!: Subscription;
  private popupCloseSubscription!: Subscription;
  private initializeSubscription!: Subscription;
  private statusChangeSubscription!: Subscription;
  private revokeChoiceSubscription!: Subscription;
  private noCookieLawSubscription!: Subscription;

  constructor(private ccService: NgcCookieConsentService, private title: Title) {


    if (environment.gaTrackingId) {
      // register google tag manager
      const gTagManagerScript = document.createElement('script');
      gTagManagerScript.async = true;
      gTagManagerScript.src = `https://www.googletagmanager.com/gtag/js?id=${environment.gaTrackingId}`;
      document.head.appendChild(gTagManagerScript);

      // register google analytics
      const gaScript = document.createElement('script');
      gaScript.innerHTML = `
        window.dataLayer = window.dataLayer || [];
        function gtag() { dataLayer.push(arguments); }
        gtag('js', new Date());
        gtag('config', '${environment.gaTrackingId}');
      `;
      document.head.appendChild(gaScript);

      this.notTrackScript = document.createElement('script');
      this.notTrackScript.innerHTML = `window['ga-disable-${environment.gaTrackingId}'] = true;`
      document.head.appendChild(this.notTrackScript)

      this.trackScript = document.createElement('script');
      this.trackScript.innerHTML = `window['ga-disable-${environment.gaTrackingId}'] = false;`
    }

  }

  ngOnInit(): void {

    this.statusChangeSubscription = this.ccService.statusChange$.subscribe(
      (event: NgcStatusChangeEvent) => {
        // you can use this.ccService.getConfig() to do stuff...
        console.log(`initialized: ${JSON.stringify(event)}`);
        if (event.status === 'allow') {
          document.head.removeChild(this.notTrackScript)
          document.head.appendChild(this.trackScript)
          location.reload()
        }

      });

  }
  ngOnDestroy(): void {
    // unsubscribe to cookieconsent observables to prevent memory leaks
    this.popupOpenSubscription.unsubscribe();
    this.popupCloseSubscription.unsubscribe();
    this.initializeSubscription.unsubscribe();
    this.statusChangeSubscription.unsubscribe();
    this.revokeChoiceSubscription.unsubscribe();
    this.noCookieLawSubscription.unsubscribe();
  }
}

问题分析

  1. 脚本执行顺序错误:GA初始化脚本先于禁用脚本执行,GA初始化时未读取到ga-disable-*变量,导致默认禁用逻辑可能失效;用户授权后刷新页面,又重新执行初始流程,再次设置禁用状态,无法激活GA。
  2. 依赖页面刷新:location.reload()会重置应用状态,无法持久化用户的授权选择,且GA需要在授权后主动重新初始化才能开始追踪。
  3. 未初始化的订阅变量:代码中声明的多个订阅变量(如popupOpenSubscription)未赋值,直接在ngOnDestroy中销毁会抛出错误。

解决方案

修改后的代码优化了执行顺序,移除不必要的刷新,处理订阅变量,并持久化授权状态:

import { Component, OnInit, OnDestroy } from '@angular/core';
import { NgcCookieConsentService, NgcStatusChangeEvent } from 'ngx-cookieconsent';
import { Subscription } from 'rxjs';
import { environment } from 'src/environments/environment';
import { Title } from '@angular/platform-browser';

declare var gtag: Function;

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit, OnDestroy {
  isShow?: boolean;
  topPosToStartShowing = 100;
  private gaTrackingId = environment.gaTrackingId;

  // 初始化所有订阅变量为null
  private popupOpenSubscription?: Subscription;
  private popupCloseSubscription?: Subscription;
  private initializeSubscription?: Subscription;
  private statusChangeSubscription?: Subscription;
  private revokeChoiceSubscription?: Subscription;
  private noCookieLawSubscription?: Subscription;

  constructor(private ccService: NgcCookieConsentService, private title: Title) {
    if (this.gaTrackingId) {
      // 1. 先设置默认禁用GA
      window[`ga-disable-${this.gaTrackingId}`] = true;

      // 2. 加载GTAG脚本
      const gTagManagerScript = document.createElement('script');
      gTagManagerScript.async = true;
      gTagManagerScript.src = `https://www.googletagmanager.com/gtag/js?id=${this.gaTrackingId}`;
      document.head.appendChild(gTagManagerScript);

      // 3. 初始化GTAG基础逻辑
      const gaScript = document.createElement('script');
      gaScript.innerHTML = `
        window.dataLayer = window.dataLayer || [];
        function gtag() { dataLayer.push(arguments); }
        gtag('js', new Date());
      `;
      document.head.appendChild(gaScript);
    }
  }

  ngOnInit(): void {
    // 检查用户已有的Cookie选择,初始化GA状态
    const currentConsent = this.ccService.getStatus();
    this.updateGaStatus(currentConsent.status);

    // 监听Cookie状态变化
    this.statusChangeSubscription = this.ccService.statusChange$.subscribe(
      (event: NgcStatusChangeEvent) => {
        this.updateGaStatus(event.status);
      });
  }

  private updateGaStatus(status: string): void {
    if (!this.gaTrackingId) return;

    if (status === 'allow') {
      // 启用GA并重新初始化
      window[`ga-disable-${this.gaTrackingId}`] = false;
      gtag('config', this.gaTrackingId);
    } else {
      // 禁用GA
      window[`ga-disable-${this.gaTrackingId}`] = true;
    }
  }

  ngOnDestroy(): void {
    // 只销毁已初始化的订阅,避免报错
    this.popupOpenSubscription?.unsubscribe();
    this.popupCloseSubscription?.unsubscribe();
    this.initializeSubscription?.unsubscribe();
    this.statusChangeSubscription?.unsubscribe();
    this.revokeChoiceSubscription?.unsubscribe();
    this.noCookieLawSubscription?.unsubscribe();
  }
}

关键优化点

  • 执行顺序调整:先设置ga-disable-*为true,再加载GA脚本,确保GA初始化时处于禁用状态。
  • 移除页面刷新:直接修改全局变量并调用gtag('config', ...)重新初始化GA,无需刷新页面即可生效。
  • 持久化状态处理:在ngOnInit中检查用户已有的Cookie选择,初始化GA状态,确保刷新页面后保持用户的选择。
  • 安全销毁订阅:使用可选链操作符?.只销毁已赋值的订阅变量,避免空值报错。

内容的提问来源于stack exchange,提问作者Utkarsh Khare

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 14:05:17