64 votes

Ajouter dynamiquement une méta-description en fonction de l'itinéraire en Angular

J'utilise Angular 5 pour créer un petit site Web de type brochure. Jusqu'à présent, j'ai configuré mes routes, et le titre de la page change dynamiquement en fonction de la route activée. J'ai réussi à le faire fonctionner en suivant les instructions de ce blog : https://toddmotto.com/dynamic-page-titles-angular-2-router-events

Je stocke actuellement mes itinéraires et mes titres dans app.module.ts comme tel :

imports: [
    BrowserModule,
    RouterModule.forRoot([
      { 
        path: '', 
        component: HomeComponent,
        data: {
          title: 'Home'
        }
      },
      { 
        path: 'about', 
        component: AboutComponent,
        data: {
          title: 'About'
        } 
      },
      { 
        path: 'products-and-services', 
        component: ProductsServicesComponent,
        data: {
          title: 'Products & Services'
        }  
      },
      { 
        path: 'world-class-laundry', 
        component: LaundryComponent,
        data: {
          title: 'World Class Laundry'
        }  
      },
      { 
        path: 'contact', 
        component: ContactComponent,
        data: {
          title: 'Contact'
        }  
      },
      { 
        path: '**', 
        component: NotFoundComponent,
        data: {
          title: 'Page Not Found'
        }  
      }
    ])
  ],

J'aimerais également y stocker mes méta-descriptions, si je les ajoute sous la rubrique data: serait assez facile.

Je récupère les données du titre avec le code suivant, qui est indiqué dans le lien du blog ci-dessus :

ngOnInit() {
    this.router.events
      .filter((event) => event instanceof NavigationEnd)
      .map(() => this.activatedRoute)
      .map((route) => {
        while (route.firstChild) route = route.firstChild;
        return route;
      })
      .filter((route) => route.outlet === 'primary')
      .mergeMap((route) => route.data)
      .subscribe((event) => {
        this.titleService.setTitle(event['title']);
      });
  }

Ma question est donc la suivante : existe-t-il un moyen de définir dynamiquement la méta-description en utilisant la même méthode ? S'il existe un moyen de combiner les fonctions de titre de page et de méta-description, ce serait l'idéal.

Je n'ai qu'une formation très limitée sur Angular, donc c'est peut-être une question de débutant. Je suis plutôt du genre designer/css/html.

0 votes

Depuis angular 4, il existe déjà un service intégré qui fait cela import { Meta } de '@angular/platform-browser' ; voir ici angular.io/api/platform-browser/Meta

0 votes

@elasticrash Oui, je me suis renseigné sur Meta. Je suis plus intéressé par la façon de mettre en œuvre Meta dans ce que j'ai déjà.

0 votes

Où se trouve la méta-description ?

110voto

Okan Aslankan Points 1230

Tout d'abord, créez un SEOService ou quelque chose comme ci-dessous :

import {Injectable} from '@angular/core'; 
import { Meta, Title } from '@angular/platform-browser';

@Injectable({
  provideIn: 'root' // Add this to ensure your SEO service will be app-wide available
})
export class SEOService {
  constructor(private title: Title, private meta: Meta) { }

  updateTitle(title: string) {
    this.title.setTitle(title);
  }

  updateOgUrl(url: string) {
    this.meta.updateTag({ name: 'og:url', content: url })
  }

  updateDescription(desc: string) {
    this.meta.updateTag({ name: 'description', content: desc })
  }
}

Après avoir injecté le SEOService dans votre composant (app.component.ts de préférence), définissez les balises méta et le titre dans la méthode OnInit

ngOnInit() {
    this.router.events.pipe(
       filter((event) => event instanceof NavigationEnd),
       map(() => this.activatedRoute),
       map((route) => {
         while (route.firstChild) route = route.firstChild;
         return route;
       }),
       filter((route) => route.outlet === 'primary'),
       mergeMap((route) => route.data)
      )
      .subscribe((event) => {
        this._seoService.updateTitle(event['title']);
        this._seoService.updateOgUrl(event['ogUrl']);
        //Updating Description tag dynamically with title
        this._seoService.updateDescription(event['title'] + event['description'])
      }); 
    }

Ensuite, configurez vos routes comme suit

      { 
        path: 'about', 
        component: AboutComponent,
        data: {
          title: 'About',
          description:'Description Meta Tag Content',
          ogUrl: 'your og url'
        } 
      },

À mon avis, il s'agit d'une façon claire de traiter les métabalises. Vous pouvez mettre à jour les balises spécifiques à Facebook et Twitter plus facilement.

1 votes

Tout est en place, mais "_seoService" me pose problème dans app.component. Il dit : "[ts] La propriété 'seoService' n'existe pas dans le type 'AppComponent'". Ce qui est logique. Comment dois-je définir "_seoService" ?

3 votes

Importez SEOService dans la section des fournisseurs de votre app.module.ts. Puis, dans votre composant où vous définissez les métabalises et les titres, injectez SEOService dans le constructeur de la manière suivante constructor(public _seoService: SEOService)

3 votes

Vive Okan ! Ça a l'air de fonctionner comme un charme. Merci !

18voto

Walgermo Points 41

Solution Angular 6+ et RxJS 6+ pour définir dynamiquement le titre lors d'un changement de route

Si/quand vous passez à Angular 6, voici la solution.

Ce service :

  • Mise à jour du titre méta en cas de changement de route.
  • Possibilité de remplacer le titre pour toutes les raisons que vous souhaitez.

Créez/modifiez votre service SEO/méta comme suit.

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

@Injectable({
    providedIn: 'root'
})
export class MetaService {
    constructor(
        private titleService: Title,
        private meta: Meta,
        private router: Router,
        private activatedRoute: ActivatedRoute
    ) { }

    updateMetaInfo(content, author, category) {
        this.meta.updateTag({ name: 'description', content: content });
        this.meta.updateTag({ name: 'author', content: author });
        this.meta.updateTag({ name: 'keywords', content: category });
    }

    updateTitle(title?: string) {
        if (!title) {
            this.router.events
                .pipe(
                    filter((event) => event instanceof NavigationEnd),
                    map(() => this.activatedRoute),
                    map((route) => {
                        while (route.firstChild) { route = route.firstChild; }
                        return route;
                    }),
                    filter((route) => route.outlet === 'primary'),
                    mergeMap((route) => route.data)).subscribe((event) => {
                        this.titleService.setTitle(event['title'] + ' | Site name');
                    });
        } else {
            this.titleService.setTitle(title + ' | Site name');
        }
    }
}

Importez votre service et appelez-le dans le contructeur.

app.component.ts

constructor(private meta: MetaService) {
    this.meta.updateTitle();
}

Et cela nécessite encore de formater les routes comme ceci.

Route file.ts

{ 
    path: 'about', 
    component: AboutComponent,
    data: {
      title: 'About',
      description:'Description Meta Tag Content'
    } 
  },

J'espère que cela vous aidera, vous et les autres personnes qui cherchent à mettre à jour le titre/méta de façon dynamique dans Angular 6.

1 votes

Où appelez-vous la fonction updateMetaInfo() ? Elle devrait se trouver dans app.component.ts sous la forme this.meta.updateTitle(); ?

13voto

estus Points 5252

Title y Meta sont des fournisseurs qui ont été introduits dans Angular 4 et qui sont censés faire cela à la fois du côté serveur et du côté client.

Pour créer ou mettre à jour title et description meta tag, c'est le cas :

import { Meta, Title } from '@angular/platform-browser';

...

constructor(public meta: Meta, public title: Title, ...) { ... }

...

this.meta.updateTag({ name: 'description', content: description }); 
this.title.setTitle(title);

2 votes

Je vais essayer ceci, si cela fonctionne alors c'est la réponse.

1 votes

Je cherchais une méthode rapide, facile et correcte pour mettre à jour les balises de titre et les métadonnées, et la voici ! Merci beaucoup de nous avoir fourni cette méthode. Si je pouvais le marquer comme étant la réponse, je le ferais totalement. Si je peux faire une petite correction, cependant, ces éléments "this.meta..." doivent être placés à l'intérieur des crochets du constructeur { }. C'est comme ça que ça a fonctionné pour moi. constructor(public title : Title, public meta : Meta) { this.title.setTitle('C'est le titre de ma page') ; this.meta.updateTag({nom : 'description', content : 'C'est ma description'}) ; }

0 votes

@michaelt Content que ça ait marché pour vous. ... signifiait que this.meta est utilisé quelque part dans la même classe. Cela peut être ngOnInit ou autre.

2voto

Kurkov Igor Points 46

L'utilisation de données (titre, description, etc.) dans le tableau des routes n'est pas très cohérente, nous pouvons regrouper toutes les données en un seul endroit. De plus, en 2021, nous pouvons utiliser les outils Angular courants dès le départ :

seo-sitemap.ts

export const seoSitemap: ISitemapTag[] = [
  { customUrl: '/contact', title: null, description: 'Some description there', image: '/assets/path/to/image' },
{ customUrl: '/about', title: 'custom about title', description: 'Some description about', image: '/assets/path/to/another-image' }
];

export interface ISitemapTag {
  customUrl: string;
  title: string | null;
  description: string | null;
  image: string | null;
}

metatags.service.ts :

import { Injectable } from '@angular/core';
import { Meta, MetaDefinition, Title } from '@angular/platform-browser';

@Injectable()
export class MetatagsService {
  constructor(private title: Title, private meta: Meta) {}

  updateTitle(title: string) {
    this.title.setTitle(title);
  }

  updateTag(tag: MetaDefinition) {
    this.meta.updateTag(tag);
  }

  updateTags(tags: Array<MetaDefinition | null>) {
    tags.forEach((tag) => {
      tag && this.meta.updateTag(tag);
    });
  }
}

app.component.ts

import { MetatagsService } from './shared/services/metatags.service';
import { seoSitemap } from './seoSitemap';

constructor() {
    this.sub = this.router.events.subscribe((event: Event) => {
      if (event instanceof NavigationEnd) {
        this.setMetaTags(event);
      }
    });
}

ngOnDestroy() { this.sub && this.sub.unsubscribe() }

private setMetaTags(event: NavigationEnd) {
      const item = seoSitemap.find((i) => event.urlAfterRedirects === i.customUrl);
      if (item) {
        if (item.title) this.metatagsService.updateTitle(item.title);

        this.metatagsService.updateTags([
          item.description ? { name: 'description', content: item.description } : null,
          item.image ? { name: 'image', content: item.image } : null,
        ]);
        this.metatagsService.updateTag({ property: 'og:url', content: window.location.href });
      } else {
        this.metatagsService.updateTitle('Common title there');
      }
  }

0 votes

C'est une solution élégante

1voto

Nikhil Points 81

Les pages Angular étant rendues côté client, les robots d'exploration ne peuvent pas détecter les balises méta. La plupart des crawlers n'exécutent pas le javascript au moment de l'exécution, ce qui fait que les métabalises dynamiques ne sont pas détectées. Cela est vrai même pour Facebook et Twitter.

Il est nécessaire d'utiliser Angular Universal pour le rendu côté serveur ou un service de prérendu, par exemple prerender.io

Edit:- Je suis tombé sur un bon tutoriel youtube à ce sujet. Voici le lien, https://www.youtube.com/watch?v=lncsmB5yfzE

1 votes

Google rend maintenant la page et la plupart des autres moteurs de recherche le font.

0 votes

Facebook ne le fait toujours pas. Si vous testez dans les outils de développement de Facebook, vous verrez qu'il ne détecte toujours pas les balises.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X