Dynamic Meta Tags In Angular

Dynamic Meta Tags In Angular

In this article, we will learn how to add dynamic meta tags to Angular. In the Angular Routes, we will start by defining the Meta Tags. After that, to keep track of the route change, use the Meta Service and NavigationEnd router event. We will update the Meta Tags when the route changes.

Meta Tags

To add/remove meta tags, we use Angular's Meta Service. It offers the subsequent techniques.

  • addTag()
  • addTags()
  • getTag()
  • getTags()
  • updateTag
  • removeTag
  • removeTagElement

We must import the root module of the Meta Service before we can inject it into the Angular Providers, as seen below.

import { BrowserModule, Meta } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
 
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
 
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [Meta],
  bootstrap: [AppComponent]
})
export class AppModule { }

Additionally, use Angular Dependency Injection to first inject the Meta Service into the component class. To manipulate the Tags, use any of the Meta Service's techniques.

import { Component, OnInit } from '@angular/core';
import { Meta, MetaDefinition } from '@angular/platform-browser';
 
@Component({
  template: `<h1>First Component</h1>`
})
export class FirstComponent {
 
  constructor(private metaService: Meta) {
    this.addTag();
  }
 
  addTag() {
    this.metaService.addTag({ name: 'description', content: 'Article Description' });
    this.metaService.addTag({ name: 'robots', content: 'index,follow' });
    this.metaService.addTag({ property: 'og:title', content: 'Content Title for social media' });
  }
 
}

Dynamic Meta Tags

It can be a hassle to add Meta tags to component classes. The ideal approach is to define all meta tags in one location, preferably at the same time that we establish the routes. We can read the router's Tags and update Mega tags as the route changes.

Example

a new Angular application should be made. As indicated below, add HomeComponent, FirstComponent, SecondComponent, SecondAComponent, and ThirdComponent.

Add the following code under the home.component.ts:

import { Component, OnInit } from '@angular/core';
import { Meta, MetaDefinition } from '@angular/platform-browser';
 
@Component({
  template: `<h1>Home Component</h1>`
})
export class HomeComponent {
}

Add the following code under the first.component.ts:

import { Component, OnInit } from '@angular/core';
import { Meta, MetaDefinition } from '@angular/platform-browser';
 
@Component({
  template: `<h1>First Component</h1>`
})
export class FirstComponent {
}

Add the following code under the  second.component.ts:

import { Component, OnInit } from '@angular/core';
import { Meta, MetaDefinition } from '@angular/platform-browser';
 
@Component({
  template: `<h1>Second Component</h1>`
})
export class SecondComponent {
}

Add the following code under the  secondA.component.ts:

import { Component, OnInit } from '@angular/core';
import { Meta, MetaDefinition } from '@angular/platform-browser';
 
@Component({
  template: `<h1>Second A Component</h1>`
})
export class SecondAComponent {
}

Add the following code under the third.component.ts:

import { Component, OnInit } from '@angular/core';
import { Meta, MetaDefinition } from '@angular/platform-browser';
 
@Component({
  template: `<h1>Third Component</h1>`
})
export class ThirdComponent {
}

Meta Tags in Route

The following step is adding Meta tags to the route.

Open the routes and the app-routing.module.ts as shown below. In route data, add the Meta Tags property. To pass static or dynamic data to routed components, we can use the Route data. The Route Data also includes the title.

import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { FirstComponent } from './first.component';
import { SecondComponent } from './second.component';
import { SecondAComponent } from './secondA.component';
import { ThirdComponent } from './third.component';
import { HomeComponent } from './home.component';
 
 
const routes: Routes = [
  {
    path: '', component: HomeComponent, pathMatch: 'full',
    data: {
      title: 'Title for Home Component',
      descrption: 'Description of Home Component',
      ogTitle: 'Description of Home Component for social media',
    }
  },
  {
    path: 'first', component: FirstComponent,
    data: {
      title: 'Title for First Component',
      descrption: 'Description of First Component',
      robots: 'noindex, nofollow',
      ogTitle: 'Description of First Component for social media',
    }
  },
  {
    path: 'second', children:
      [
        {
          path: '', component: SecondComponent, pathMatch: 'full',
          data: {
            title: 'Title for Second Component',
            descrption: 'Description of Second Component',
          }
        },
        {
          path: 'a', component: SecondAComponent,
          data: {
            title: 'Title for Second A Component',
            descrption: 'Description of Second A Component',
            ogTitle: 'Title of Second A Component for social media',
            ogDescription: 'Description of Second A Component for social media',
            ogImage: 'ImagePathForSocialMedia'
          }
        },
      ]
  },
  {
    path: 'third', component: ThirdComponent,
    data: {
      title: 'Title for third Component',
      descrption: 'Description of third Component',
      ogDescription: 'Description of third Component for social media',
      ogUrl: '/home'
    }
  },
];
 
@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Listen to Navigation Changes

The router fires the navigation events each time a user navigates to a new route (or page). When the navigation is successfully completed, the router raises the NavigationEnd event.

Every NavigationEnd event must be heard, and the ideal location to do it is in our root component, which is app.component.ts. The code is shown as follows.

import { Component, OnInit } from '@angular/core';
import { Title, Meta } from '@angular/platform-browser';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { filter, map } from 'rxjs/operators';
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
 
  constructor(private router: Router,
    private activatedRoute: ActivatedRoute,
    private titleService: Title,
    private metaService: Meta) {
  }
 
  ngOnInit() {
 
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd),
    )
      .subscribe(() => {
 
        var rt = this.getChild(this.activatedRoute)
 
        rt.data.subscribe(data => {
          console.log(data);
          this.titleService.setTitle(data.title)
 
          if (data.descrption) {
            this.metaService.updateTag({ name: 'description', content: data.descrption })
          } else {
            this.metaService.removeTag("name='description'")
          }
 
          if (data.robots) {
            this.metaService.updateTag({ name: 'robots', content: data.robots })
          } else {
            this.metaService.updateTag({ name: 'robots', content: "follow,index" })
          }
 
          if (data.ogUrl) {
            this.metaService.updateTag({ property: 'og:url', content: data.ogUrl })
          } else {
            this.metaService.updateTag({ property: 'og:url', content: this.router.url })
          }
 
          if (data.ogTitle) {
            this.metaService.updateTag({ property: 'og:title', content: data.ogTitle })
          } else {
            this.metaService.removeTag("property='og:title'")
          }
 
          if (data.ogDescription) {
            this.metaService.updateTag({ property: 'og:description', content: data.ogDescription })
          } else {
            this.metaService.removeTag("property='og:description'")
          }
 
          if (data.ogImage) {
            this.metaService.updateTag({ property: 'og:image', content: data.ogImage })
          } else {
            this.metaService.removeTag("property='og:image'")
          }
 
 
        })
 
      })
 
  }
 
  getChild(activatedRoute: ActivatedRoute) {
    if (activatedRoute.firstChild) {
      return this.getChild(activatedRoute.firstChild);
    } else {
      return activatedRoute;
    }
 
  }
}

The router change event is subscribed to using the following code. The NavigationEnd event is suppressed by the filter RxJS Operator. We are members of it.

this.router.events.pipe(
  filter(event => event instanceof NavigationEnd),
)
  .subscribe(() => {

To reach the current route, we recursively step through the ActivatedRoute tree in the following line.

var rt = this.getChild(this.activatedRoute)

We subscribe to the data property to retrieve the Route Data once we have the ActivateRoute of the component that is presently loaded.

rt.data.subscribe(data => {
    console.log(data);

Now, we can use the title service to set the title.

this.titleService.setTitle(data.title)

If a Meta Description is specified on the route, update it. If not, we can take away the description that was set for the prior component.

if (data.descrption) {
  this.metaService.updateTag({ name: 'description', content: data.descrption })
} else {
  this.metaService.removeTag("name='description'")
}

If no tags were defined, it is preferable to set the robots tag to follow, and index as default in situations like this.
if (data.robots) {
  this.metaService.updateTag({ name: 'robots', content: data.robots })
} else {
  this.metaService.updateTag({ name: 'robots', content: "follow,index" })
}

Add the following code under the app.component.html:

<h1>Angular Dynamic Meta Tags Example</h1>
 
<ul>
  <li><a routerlink="">Home</a> </li>
  <li><a first="" routerlink="">First</a> </li>
  <li><a routerlink="" second="">Second</a> </li>
  <ul>
    <li><a a="" routerlink="" second="">Second A</a> </li>
  </ul>
  <li><a routerlink="" third="">third</a> </li>
</ul>
 
<router-outlet></router-outlet>

Add the following code under the app.module.ts:

import { BrowserModule, Meta } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
 
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { FirstComponent } from './first.component';
import { SecondAComponent } from './secondA.component';
import { ThirdComponent } from './third.component';
import { SecondComponent } from './second.component';
import { HomeComponent } from './home.component';
 
@NgModule({
  declarations: [
    AppComponent, FirstComponent,SecondAComponent, ThirdComponent, SecondComponent, HomeComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule
  ],
  providers: [Meta],
  bootstrap: [AppComponent]
})
export class AppModule { }

Conclusion

In this article, we learned how to add dynamic meta tags to Angular using examples.

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in the comment section.

Post a Comment

Previous Post Next Post