Динамический заголовок страницы как для отображения в браузере, так и для Google Analytics в Angular

Вопрос в том:

Как динамически и централизованно настроить заголовки страниц в приложении Angular только один раз для двух целей:

  • чтобы заголовок в браузере отражал фактическую посещаемую страницу,
  • чтобы отправить определенный заголовок в Google Analytics, избегая скучного, единственного и бесполезного описания приложения Angular, применяемого ко всем страницам приложения.

person Wojciech Marciniak    schedule 21.09.2019    source источник


Ответы (1)


Мое текущее решение

Я использовал два хороших фрагмента, найденных на Github:

  • first позволяет централизованно определить заголовок страницы в конфигурации маршрутизатора только для наглядности,
  • секунда предоставляет решение для отправки навигационных событий в Google Analytics, а в одностраничном приложении — в автоматическим централизованным способом или вручную. Он получил вдохновляющий тикет с комментариями амарнатм.

Ну, идеи, представленные в этих двух, включая обсуждение проблемы, сообщалось последний может быть интегрирован таким образом:

app.routing-module.ts:

const routes: Routes = [ 
  { path: 'site/contact', component: ContactComponent, data: {title: 'Contact'}},
  ...
  // other paths
];

app.module.ts:

import {BrowserModule} from '@angular/platform-browser';
import {TitleService} from "./title.service";
import {GtagModule} from "angular-gtag";
// ...
providers: [
    // ...
    TitleService,
    GtagModule.forRoot({ trackingId: 'MY-UA-CODE', trackPageviews: false })        
    // ...   
  ]
// ...

trackPageviews: false, предложенный amarnathm, важен, так как мы будем отслеживать каждую страницу вручную. Стандартный пример кода от Jeff по умолчанию имеет значение true.

title.service.ts:

import { Injectable } from '@angular/core';
import { Router, ActivatedRoute, NavigationEnd } from '@angular/router';
import { Title } from '@angular/platform-browser';
import { filter, map, switchMap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class TitleService {
  default_title = 'My App';

  constructor(
    private router: Router,
    private activeRoute: ActivatedRoute,
    private title: Title,
    private gtag: Gtag,
    private env: Environment
  ) { }

  boot() {
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd),
      map(() => this.activeRoute),
      map(route => route.firstChild),
      switchMap(route => route.data),
      map((data) => {

        //here goes the GA reporting code            

        this.gtag.pageview({
          page_title: data && data.title ? data.title : this.default_title,
          page_path: this.router.url,
          page_location: this.env.host + this.router.url
        });

        return data && data.title ? `${data.title} • ${this.default_title}` : this.default_title;
      })
    ).subscribe((current_title) => this.title.setTitle(current_title));
  }
}

app.component.ts:

import { Component, OnInit } from '@angular/core';
import { TitleService } from './title.service';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styles: [],
})
export class AppComponent implements OnInit {

  constructor(private titleService: TitleService) { }

  ngOnInit() {
    this.titleService.boot();
  }
}

Избавьтесь от любого кода GA/Gtag, который может быть в вашем файле index.html. Это позволяет настраивать подписку на услуги GA, не полагаясь на автоматическое отслеживание, которое мы не будем использовать. В SPA index.html загружается обычно один раз и без включенного отслеживания страниц бесполезен.

Предложение по улучшению:

У меня нет ответа на:

Как использовать ActivatedRoute параметры и сопоставлять их с подробными заголовками, используемыми затем в Analytics и, при необходимости, для отображения заголовков на параметр в браузере.

person Wojciech Marciniak    schedule 21.09.2019
comment
Вам не нужно указывать службу Title из @angular/platform-browser в модуле вашего приложения, так как она уже должна быть определена в PlatformBrowserModule, который был бы определен в модуле вашего приложения. - person Edric; 21.09.2019
comment
BrowserModule на самом деле. Спасибо, @Edric, я отредактировал. - person Wojciech Marciniak; 22.09.2019