Angular 2 环境特定头部注入

Angular 2 Environment Specific Head Injection

我正在为我的 Angular2 应用程序添加 Google 跟踪代码管理器支持,但我不明白如何使用不同的容器 ID 为开发和生产注入所需的 GTM 脚本我在 GTM 中有两个容器。

有没有办法根据环境文件中的变量注入 head 标记并更改容器 ID?

我在构建过程中使用 Angular CLI。

您可以为标签管理器构建一个服务,我确实为我的公司项目构建了一个服务,它为 AdWordsGoogle Trusted Stores 和 [=15] 等提供商处理多个容器 ID 和事件=].

这是注入标签管理器脚本的模型示例版本。 (注意:由于直接使用 documentwindow,因此它不是通用的。)

export class TagManager {
private static instance: TagManager = null;
private ids: string[];
private dataLayerName: string;
private precision: number = 2;

public dataLayer: any[] = [];
public language: string;
public currency: string;

constructor(ids: string[], dataLayerName: string, language: string, currency: string) {
  if(TagManager.instance) {
    throw new Error("Error - use GoogleTagManager.getInstance()");
  }
  this.ids = ids;
  this.dataLayerName = dataLayerName;
  this.currency = currency;
  this.language = language;
  this.init();
}

private init() {
  this.ids.forEach(id => this.initContainer(id));
}

private initContainer(id: string) {
  let internal = this;
  (function(w,d,s,l,i) {
    w[l]=w[l]||[];
    w[l].push({
      'gtm.start': new Date().getTime(),
       event:'gtm.js'
    });
    let f: any = d.getElementsByTagName(s)[0];
    let j: any = d.createElement(s);
    let dl: any = l!='dataLayer'?'&l='+l:'';
    j.async=true;
    j.src= 'https://www.googletagmanager.com/gtm.js?id='+i+dl;
    f.parentNode.insertBefore(j,f);
    internal.dataLayer = w[l];
  })(window,document,'script',this.dataLayerName,id);
}

public static getInstance(ids: string | string[] = [], dataLayerName = 'dataLayer', language = 'en', currency = 'EUR') {
    ids = ids || [];
    ids = Array.isArray(ids)? ids: [ids];
    if(!TagManager.instance) {
      if(ids.length === 0) {
        return;
      }
      ids.forEach(id => {
        if(!id || (typeof id !== 'string') || id.indexOf('GTM-') !== 0) {
          console.error("Please provide a valid container ID (i.e. GTM-XXXXXX)");
        }
      })
      if(!dataLayerName || (typeof dataLayerName !== 'string')) {
        console.error("Please provide a valid name for the data layer");
      }
   }
   TagManager.instance = TagManager.instance || new TagManager(ids,   dataLayerName, language, currency);
   return TagManager.instance;
  }
}

服务示例:

@Injectable()
export class Service {
  private static instance: TagManager = null;
  private eventTracker$: ReplaySubject<any> = new ReplaySubject();
  private dataStream$: ReplaySubject<any> = new ReplaySubject();
  private currency: string;
  private precision: number = 3;
  private language: string;

  private readyTracker$: ReplaySubject<boolean> = new ReplaySubject<boolean>();

  public get settings() {
    return {
      language: this.language,
      currency: this.currency,
      precision: this.precision
    }
  }

  public get eventTrack$() {
    return this.eventTracker$.asObservable();
  }

  public get dataLayer$() {
    return this.dataStream$.asObservable();
  }

  public get isReady$() {
    return this.readyTracker$.asObservable();
  }

  public get isInitialized() {
    return !!Service.instance;
  }

  constructor() {
    this.readyTracker$.next(false);
  }

  public init(containerIds?: string[], dataLayerName?: string, language?: string, currency?: string) {
    if(Service.instance instanceof TagManager) {
      console.error('Google tag manager already loaded.');
      return;
    }
    Service.instance = TagManager.getInstance(containerIds || [], dataLayerName || 'dataLayer', language || 'en', currency || 'EUR');
    this.currency = currency;
    this.language = language;
    if(!Service.instance) {
      console.info('no gtm container installed');
      return;
    }
    this.dataLayer$.subscribe(e => {
      Service.instance.dataLayer.push(e);
    });
    this.readyTracker$.next(true);
  }

  public push(data: any) {
    this.dataStream$.next(data);
  }

  public pushCustomEvent(eventName: string, attributes: any) {
    this.push({
      event: eventName,
      attributes: attributes
    });
  }

  public pushEcommerceEvent(eventName: string, eventData: any) {
    this.push(Object.assign({}, {
      event: eventName
    }, eventData))
  }
}

AdWords 提供商示例:

@Injectable()
export class AdwordsProvider {
  constructor(private gtmService: Service) { }

  public sendConversion(id: string, value: number) {
    // build conversion 
    let conversion = {
      [Fields.Conversion.attributes.id]: id,
      [Fields.Conversion.attributes.value]: Number.parseFloat(value.toFixed(this.gtmService.settings.precision)).toString(),
      [Fields.Conversion.attributes.currency]: this.gtmService.settings.currency
    };
    // push event to dataLayer
    this.gtmService.pushCustomEvent('conversionEventName', {
     // event data
    });
  }
}

或者你可以看看 angulartics2,也许它符合你的需要。