How To Set Canonical URL Links In Angular

How To Set Canonical URL Links In Angular

In this article, we will learn how to set Canonical URL links in Angular. The Angular does not have a Link Service, in contrast to the Meta Service and Title Service. However, by injecting the DOCUMENT DI Token, we can obtain the dom object, which we can then use to change the DOM. When the app is running in the browser, this token returns the dom object. It is useful for adding or changing the Canonical URL in our application.

Canonical URL

Search engines can be informed about duplicate content on our site using a canonical URL. There could be a number of factors that lead to duplicate content.

For instance, the Samsung Galaxy A51 smartphone is offered in three shades: blue, white, and black. To accomplish this, we often use Angular's query strings.

https://example.com/samsung-galaxy-a51?color="black"
https://example.com/samsung-galaxy-a51?color="white"
https://example.com/samsung-galaxy-a51?color="blue"

The search engines index all of these as three separate pages. They will be designated as duplicate content as well. Google won't penalize you for this, but your page can drop in the rankings.

Notifying Google that you have duplicate material is the best course of action in this situation. Additionally, let it know which of the three items listed above should be regarded as original content.

The following tag is added to the HTML's head section to generate a canonical tag.

<link href="https://example.com/samsung-galaxy-a51" rel="canonical"></link>

We must have access to the DOM element in order to insert a link tag. For this, Angular provides the auxiliary object Document.

Document DI Token

The primary rendering context is represented by a DOCUMENT DI Token. This is the DOM Document in a browser.

When you inject a DOCUMENT into Angular when it is executing in a browser, it injects an instance of the DOM Document. You can use libraries like domino, which will give DOM in the Node Server if you are using server-side rendering.

Using the Meta Service & Title Service, we discovered how to manage the title & meta tags. Both of these services modify the title and meta tags using the Document.

You must import the DOCUMENT from the @angular/common library in order to use it.

import { DOCUMENT } from '@angular/common';

Using the DOCUMENT DI token, inject it into the component as seen below.

constructor(@Inject(DOCUMENT) private dom) {
}

How to Set canonical URL in Angular

The rel="canonical" tag addition using the DOM Document is demonstrated in the code below.

updateCanonicalUrl(url:string){
  const head = this.dom.getElementsByTagName('head')[0];
  var element: HTMLLinkElement= this.dom.querySelector(`link[rel='canonical']`) || null
  if (element==null) {
    element= this.dom.createElement('link') as HTMLLinkElement;
    head.appendChild(element);
  }
  element.setAttribute('rel','canonical')
  element.setAttribute('href',url)
}

First, a reference to the HTML head section is provided.

const head = this.dom.getElementsByTagName('head')[0];

Next, we search beneath the link tag for the canonical tag.

var element: HTMLLinkElement= this.dom.querySelector(`link[rel='canonical']`) || null

If the tag is missing, it is added under the head section.

if (element==null) {
  element= this.dom.createElement('link') as HTMLLinkElement;
  head.appendChild(element);
}

Finally, we add the URL to the canonical tag.

element.setAttribute('rel','canonical')
element.setAttribute('href',url)

Dynamically Updating Canonical URL

The canonical URL can be dynamically updated by using the Route. We demonstrated how to use the Title Service to dynamically set the Title. You can also look at Angular's Dynamic Meta Tags, which uses a related method. The canonical URL is updated using the same method.

Update the routes first, then add the canonical tag to each route's Route Data.

const routes: Routes = [
  {
    path: '', component: FirstComponent, pathMatch: 'full',
    data: {
      title: 'Title for First Component',
      descrption: 'Description of First Component',
      ogTitle: 'Description of First Component for social media',
      canonical:'/first'
    }
  },

Subscribe to the NavigationEnd router event in the app.component. Search the route tree recursively for the currently active route (getChild method). Read the ActivatedRoute's canonical URL Route data.

import { Component, OnInit, Inject } from '@angular/core';
import { Title, Meta, ɵDomAdapter } from '@angular/platform-browser';
import { Router, NavigationEnd, ActivatedRoute } from '@angular/router';
import { filter, map } from 'rxjs/operators';
import { DOCUMENT } from '@angular/common';
 
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
 
 constructor(@Inject(DOCUMENT) private dom,
   private router: Router,
   private activatedRoute: ActivatedRoute) {
 }
 
 ngOnInit() {
 
    const hostName="https://www.example.com"
    this.router.events.pipe(
      filter(event => event instanceof NavigationEnd),
    )
      .subscribe(() => {
 
        var rt = this.getChild(this.activatedRoute)
 
        rt.data.subscribe(data => {
          //Set Canonical URL
          if (data.canonical) {
            this.updateCanonicalUrl(hostName+data.canonical);
          } else {
            this.updateCanonicalUrl(hostName+this.router.url);
          }
          //You can set the Meta & Title here
        })
 
      })
 
  }
}

In the example, the hostName is hard coded. Additionally, you may add the hostname property to an angular configuration file and read it using the APP INITIALIZER.

Canonical as Service

The alternative is to construct the SEOService and call it from each component's ngOnInit.

import { Injectable, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';
 
@Injectable({
   providedIn: 'root'
})
export class SEOService { 
 
  constructor(@Inject(DOCUMENT) private dom) { 
  }
    
  updateCanonicalUrl(url:string){
    const head = this.dom.getElementsByTagName('head')[0];
    var element: HTMLLinkElement= this.dom.querySelector(`link[rel='canonical']`) || null
    if (element==null) {
      element= this.dom.createElement('link') as HTMLLinkElement;
      head.appendChild(element);
    }
    element.setAttribute('rel','canonical')
    element.setAttribute('href',url)
  }
}  

Any component you want to use to set the canonical URL can be called that.

import { Component } from '@angular/core';
import { SEOService } from './seo.service';
 
@Component({
  templateUrl: './first.component.html',
  styleUrls: ['./first.component.css']
})
 
export class FirstComponent{
  const hostName="https://www.example.com"
  constructor(private seoService: SEOService) { }
 
  ngOnInit() {
    this.seoService.updateCanonicalUrl(hostName+'/first');
  }
}

Conclusion

In this article, we learned how to set Canonical URL links in Angular. 

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