0

我正在爲我的Angular2應用程序添加Google Tag Manager支持,但我不明白如何使用不同的容器ID注入所需的GTM腳本以進行開發和生產,因爲我已經有兩個GTM中的容器。Angular 2環境特定頭部注入

有沒有辦法將注入到head標籤並根據環境文件中的變量更改容器ID?

我正在使用Angular CLI作爲構建過程的一部分。

回答

0

你可以建立的標籤管理服務,我做了自己編譯一個爲我公司的項目,它可以處理多個集裝箱的ID和事件像AdWordsGoogle Trusted StoresAnalytics提供商。

這是注入標籤管理器腳本的模型的示例版本。 (注:這不是普遍的準備,由於直接使用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,也許它符合你的需求。

+0

我在看angulartics2,但您仍然需要在頭部添加跟蹤代碼..我可能會嘗試類似於您在此處完成的操作。我想你可以命名gtm初始化函數,然後在服務構造函數中調用它。 – kermitology

+0

你可以在你的服務中使用'TagManager.getInstance'來初始化它(如果你需要除'en'和'EUR'之外的其他東西,它會收集你的containerIds,language和currency,我已經添加了一個服務示例。 – cyrix