Skip to main content

How to set Canonical URL in Angular 7

SEO is an integral part of any website and Canonical URLs can help to inform search engines about identical or “duplicate” content appearing on multiple URLs. A canonical tag (AKA “rel canonical”) tells search engines to use the URL defined in the canonical tag to appear in search results. You can refer this guide to find more about the importance of Canonical URL. It’s important to create the canonical URLs dynamically as a static canonical URL can also impact your search engine results. In this short post, we’ll see how to set Canonical URL in Angular 7.

How to set Canonical URL in Angular 7

If you want to learn all of Angular, I want to personally recommend ng-book as the single-best resource out there. You can get a copy here. The book is updated to Angular 7.

First, we need to create a singleton service. Why singleton? So that the service instance can be shared across multiple components. The components need to imports and reference the service in its constructor.

Create an angular service named MetaService with the following code:

import { Injectable, Inject } from '@angular/core';
import { DOCUMENT } from '@angular/common';

@Injectable({
   providedIn: 'root'
})

export class MetaService { 
   constructor(@Inject(DOCUMENT) private dom) { }
   
   createCanonicalURL() {
      let link: HTMLLinkElement = this.dom.createElement('link');
      link.setAttribute('rel', 'canonical');
      this.dom.head.appendChild(link);
      link.setAttribute('href', this.dom.URL);
   }
} 

The above code does the following things.

  • As the service needs to be a singleton service, starting with Angular 6 this is done by setting providedIn to root on the service’s @Injectable decorator [Line:4-6]. To use @Injectable, we need to import the required modules [Line:1]. You can read more about the singleton service on New Way of Providing Shared Instance of a Service in Angular 6
  • As we need to manipulate the DOM, we need something in Angular which represents DOM. DOCUMENT in Angular is used as browser DOM document. It is a DI token representing the main rendering context. Angular creates DOCUMENT DI token as following.
    const DOCUMENT: InjectionToken<Document>;

    It is imported from @angular/common library and it is injected in the constructor using @Inject decorator [Line:9].
    The dom variable represents HTML DOM and we can access and manipulate DOM properties such as creating a canonical link at runtime.

  • The function createCanonicalURL uses Angular document to create a link element and set canonical URL and appends it to the HEAD section.

Use service in angular component

Now, let’s use this service in the angular component. To use this service in any angular component, 3 things needs to be done.

  • Import the service.
  • Inject the service in the component constructor.
  • Call the createCanonicalURL function in ngOnInit event.
import { Component } from '@angular/core';
import { MetaService } from './meta.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  title = 'Set Canonical URL in Angular 7';

  constructor(private metaService: MetaService) { }

  ngOnInit() {
    this.metaService.createCanonicalURL();
  }
}

Run the application and check the canonical URL via the inspector tool.

How to set Canonical URL in Angular 7

We can improve the usability of the createCanonicalURL method by passing an optional URL parameter. This would help to pass a different canonical URL reference for the page. Like,

createCanonicalURL(url?:string) {
    let canURL = url == undefined ? this.dom.URL : url;
    let link: HTMLLinkElement = this.dom.createElement('link');
    link.setAttribute('rel', 'canonical');
    this.dom.head.appendChild(link);
    link.setAttribute('href', canURL);
}

Thank you for reading. Keep visiting this blog and share this in your network. Please put your thoughts and feedback in the comments section.

PS: If you found this content valuable and want to return the favour, then Buy Me A Coffee

15 thoughts to “How to set Canonical URL in Angular 7”

  1. The canonical link stays in the document when you navigate to another route. How would you find the old one, remove it, and add another? Or find the existing link element and replace the URL? Thank you.

    1. Nevermind, duh! I had to remove them manually on the ngOnDestroy() event, lol. Thanks for the article thanks for sharing.

      1. Hi, I am very new to angular and I face the same problem how are you able to remove the link on ngOnDestroy()? Did you have to add another method on your SEO service?
        I’m sorry if this is a dumb question.

        1. Just do this and you are good to go

          const canonical: any = document.querySelectorAll(‘link[rel=”canonical”]’);
          canonical[0].parentElement.removeChild(canonical[0]);

          Add this code in your ngOnDestroy

        2. I changed the createCanonicalURL method to delete the old one before adding the new one;

          createCanonicalURL() {
          let oldlink: HTMLLinkElement = this.dom.querySelector(‘link[rel=canonical]’);
          if (oldlink) {
          oldlink.remove();
          }
          let link: HTMLLinkElement = this.dom.createElement(‘link’);
          link.setAttribute(‘rel’, ‘canonical’);
          this.dom.head.appendChild(link);
          link.setAttribute(‘href’, this.dom.URL);
          }

      2. I think a better approach would be to set an id for the canonical link element and update it in every ngOnInit, something like this:

        setCanonicalURL() {
        let link: HTMLLinkElement = this.dom.getElementById(‘canonicalMeta’);
        link.setAttribute(‘href’, this.dom.URL);
        }

  2. A separate issue I’ve noticed is that because the tag is being appended if you route to different pages you’ll end up with multiple link tags. For me time permitting I’ll see if I can get the method to parse the head first and remove any existing canonical link tag but you might want to note this here.

  3. I have used this in Angular 7, but it’s not showing website address, so instead of adding `www.example.com` it’s just adding `/` for the home page, some of the inner pages too.

  4. Hi, I think you just viewed your page in view source, you should check the content or canonical url details of the page using inspect element console option.

    To view it in your view source itself, you must enable angular universal for SSR.

Leave a Reply

Your email address will not be published. Required fields are marked *