Skip to content

Instantly share code, notes, and snippets.

@djabif
Last active September 22, 2020 17:22
Show Gist options
  • Save djabif/13f87d2eac7d6d4eb33f77e96f170d4d to your computer and use it in GitHub Desktop.
Save djabif/13f87d2eac7d6d4eb33f77e96f170d4d to your computer and use it in GitHub Desktop.
Angular directive to set dynamic Meta Tags for SEO
import { Directive, OnDestroy, OnInit, Inject } from '@angular/core';
import { ActivatedRoute, NavigationEnd, Router } from '@angular/router';
import { Meta, Title } from '@angular/platform-browser';
import { filter, map, mergeMap } from 'rxjs/operators';
import { DOCUMENT, PlatformLocation } from '@angular/common';
@Directive({
selector: '[appSeo]'
})
export class SEODirective implements OnInit, OnDestroy {
_routerSubscription: any;
constructor(
private activatedRoute: ActivatedRoute,
private router: Router,
private meta: Meta,
private title: Title,
@Inject(DOCUMENT) private document: Document,
private platformLocation: PlatformLocation
) {}
ngOnInit(): void {
this._routerSubscription = 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 => {
// tslint:disable-next-line:no-string-literal
const routeData = event['seo'];
if (routeData && routeData.seo) {
const title = routeData.seo.title;
const description = routeData.seo.description;
const keywords = routeData.seo.keywords;
const imageUrl = routeData.seo.image_url || 'https://s3-us-west-2.amazonaws.com/ionicthemes/imgs/logofacebook.png';
this.title.setTitle(title);
this.meta.updateTag({ name: 'description', content: description }, 'name="description"');
this.meta.updateTag({ name: 'keywords', content: keywords }, 'name="keywords"');
this.meta.updateTag({ name: 'twitter:title', content: title }, 'name="twitter:title"');
this.meta.updateTag({ name: 'twitter:description', content: description }, 'name="twitter:description"');
this.meta.updateTag({ name: 'twitter:image', content: imageUrl }, 'name="twitter:image"');
this.meta.updateTag({ name: 'DC.title', content: title }, 'name="DC.title"');
this.meta.updateTag({ name: 'DC.description', content: description }, 'name="DC.description"');
this.meta.updateTag({ property: 'og:title', content: title }, 'property="og:title"');
this.meta.updateTag({ property: 'og:description', content: description }, 'property="og:description"');
this.meta.updateTag({ property: 'og:image', content: imageUrl }, 'property="og:image"');
} else {
// Maybe set default SEO values here
}
// Set Canonical URL
// If you want to set cannonical URL uncomment the following line and add your URL in getCurrentUrl();
// this.updateCanonicalUrl(this.getCurrentUrl(this.platformLocation));
});
}
updateCanonicalUrl(url: string) {
const head = this.document.getElementsByTagName('head')[0];
let element: HTMLLinkElement = this.document.querySelector(`link[rel='canonical']`) || null;
if (element == null) {
element= this.document.createElement('link') as HTMLLinkElement;
head.appendChild(element);
}
element.setAttribute('rel','canonical');
element.setAttribute('href', url);
}
getCurrentUrl(platformLocation: any){
return platformLocation.location.origin + platformLocation.location.pathname;
}
ngOnDestroy(): void {
this._routerSubscription.unsubscribe();
}
}
@djabif
Copy link
Author

djabif commented Sep 22, 2020

This directive is super helpful to be able to add meta tags dynamically to every route depending on the resolved route data. For example I use it to set the tags for our blog posts and products dynamically.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment