How to add canonical link to all routers in Angular 9?

How to add canonical link to all routers in Angular 7?

When I was trying to find a snippet on how to add canonical link to all routers in Angular 7, I was able to find out lot of snippets in stackoverflow, github and few other blogs.

But When I tested all the snippets from both stackoverflow and github, below snippet is the one which is working properly without any issues in all the use cases.

Few issues I observed with other snippets:

  1. When ever navigation is happened it is keep on adding the canonical link tags, this below snippet just keeps only one canonical link tag.
  2. Duplicate canonical link tags added due to above point 1, this below snippet uses update method which always removes and adds the canonical link tag, so this helps to keep only one canonical link tag.
  3. No update/remove to avoid the duplicates, this below snippet provides add/update and remove tag methods for different use cases.

 

This below is actually removing the duplicate tag if found and keeps only the current document url in the canonical url link.

 

How to add canonical link to all routers in Angular 7?

Please note this snippet is taken from this link only, if you are facing any issues feel free to update in this page only. I just posted this blog to help people with the correct and perfect snippet to avoid testing all the other solutions.

 

LinkService with addTag/UpdateTag and RemoveTag for different use-cases:

[code language=”javascript”] import { Injectable, Optional, RendererFactory2, ViewEncapsulation, Inject } from ‘@angular/core’; import { DOCUMENT } from ‘@angular/platform-browser’; @Injectable() export class LinkService { renderer: any; constructor( private rendererFactory: RendererFactory2, @Inject(DOCUMENT) private document ) { this.renderer =this.rendererFactory.createRenderer(this.document, { id: ‘-1’, encapsulation: ViewEncapsulation.None, styles: [], data: {} }); } updateTag(tag: LinkDefinition) { this.removeTag(tag); this.addTag(tag); } /** * Rimuove il link esistente con lo stesso atrtributo rel */ removeTag(tag: LinkDefinition) { try { const selector =this._parseSelector(tag); const canonical =this.document.querySelector(selector) const head =this.document.head; if (head ===null) { thrownew Error(‘ not found within DOCUMENT.’); } if (!!canonical) { this.renderer.removeChild(head, canonical); } } catch (e) { console.error(‘Error within linkService : ‘, e); } } /** * Inietta il link ocme ultimo child del tag */ addTag(tag: LinkDefinition) { try { const link =this.renderer.createElement(‘link’); const head =this.document.head; if (head ===null) { thrownew Error(‘ not found within DOCUMENT.’); } Object.keys(tag).forEach((prop: string) => { returnthis.renderer.setAttribute(link, prop, tag[prop]); }); // [TODO]: get them to update the existing one (if it exists) ? this.renderer.appendChild(head, link); } catch (e) { console.error(‘Error within linkService : ‘, e); } } private _parseSelector(tag: LinkDefinition): string { const attr: string = tag.rel ?’rel’:’hreflang’; return`link[${attr}=”${tag[attr]}”]`; } } export declare type LinkDefinition = { charset?: string; crossorigin?: string; href?: string; hreflang?: string; media?: string; rel?: string; rev?: string; sizes?: string; target?: string; type?: string; } & { [prop: string]: string; }; [/code]

Add this in your App Module Providers:

[code language=”javascript”] import { LinkService } from ‘./shared/services/link.service’; @NgModule( { declarations: [ AppComponent ], imports:[ ], providers: [LinkService], } ) export class AppModule { } vascript”] [/code]

And in your component, preferably Header Component,

[code language=”javascript”] import { LinkService } from “../../../shared/services/link.service”; export class HeaderComponent { constructor(private linkService: LinkService, @Inject(DOCUMENT) private document) { } ngOnInit() { this.linkService.updateTag( { rel: ‘canonical’, href: this.document.URL } ); } } [/code]

Thanks for reading this post!

Leave a Reply