Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Example working service for adding meta tags to <head/> for angular2-universal. Based on http://blog.devcross.net/2016/04/17/angular-2-universal-seo-friendly-website/
import {Injectable,Inject,ElementRef, Renderer} from '@angular/core';
//import { DOCUMENT } from '@angular/platform/common_dom';
import {DOCUMENT} from '@angular/platform-browser';
@Injectable()
export class SeoService {
private _r: Renderer;
private _el: ElementRef;
private _document: any;
/**
* Angular 2 Title Service
*/
//private titleService: Title;
/**
* <head> Element of the HTML document
*/
private headElement: any;//HTMLElement;
/**
<meta property="og:title" content="Title Here" />
*/
private ogTitle: HTMLElement;
/**
<meta property="og:type" content="article" />
*/
private ogType: HTMLElement;
/**
<meta property="og:url" content="http://www.example.com/" />
*/
private ogUrl: HTMLElement;
/**
<meta property="og:image" content="http://example.com/image.jpg" />
*/
private ogImage: HTMLElement;
/**
<meta property="og:description" content="Description Here" />
*/
private ogDescription: HTMLElement;
/**
* Inject the Angular 2 Title Service
* @param titleService
*/
constructor(@Inject(DOCUMENT) private document, element: ElementRef, renderer: Renderer) {
this._el = element;
this._r = renderer;
//super();
this._document = document;
this.headElement = this._document.head;
this.ogTitle = this.getOrCreateMetaElement('og:title','property');
this.ogType = this.getOrCreateMetaElement('og:type','property');
this.ogUrl = this.getOrCreateMetaElement('og:url','property');
this.ogImage = this.getOrCreateMetaElement('og:image','property');
this.ogDescription = this.getOrCreateMetaElement('og:description','property');
}
public setTitle(siteTitle = '',pageTitle ='',separator = ' / '){
let title = siteTitle;
if(pageTitle != '') title += separator + pageTitle;
this._document.title = title;
}
/*
* Open graph
*/
public setOgTitle(value: string) {
this._r.setElementAttribute(this.ogTitle,'content',value);
}
public setOgType(value: string) {
this._r.setElementAttribute(this.ogType,'content',value);
}
public setOgUrl(value: string) {
this._r.setElementAttribute(this.ogUrl,'content',value);
}
public setOgImage(value: string) {
this._r.setElementAttribute(this.ogImage,'content',value);
}
public setOgDescription(value: string) {
this._r.setElementAttribute(this.ogDescription,'content',value);
}
/**
* get the HTML Element when it is in the markup, or create it.
* @param name
* @returns {HTMLElement}
*/
private getOrCreateMetaElement(name: string,attr: string): HTMLElement {
let el: HTMLElement;
var prop = ((attr != null)? attr : 'name');
el = this._r.createElement(this.headElement,'meta',null);
this._r.setElementAttribute(el,prop,name);
return el;
}
}
@jkufrin
Copy link

jkufrin commented Jul 13, 2016

Great service. I modified this and it works well with Angular Universal. I did catch one minor bug that was crashing prerender on a hard reload.

I had to update line 60:
this._document.title = title;
to
this._document.head.title = title;

@threesquared
Copy link

threesquared commented Jul 15, 2016

I get an the following error using this with angular universal

Error: Uncaught (in promise): No provider for ElementRef! (SeoService -> ElementRef)

@maxiar
Copy link

maxiar commented Aug 29, 2016

HI! Excelent works, but I'm a benninger in Angular 2, Did you have an example with this SEO Services and Angular universal fully working.. Can you share it?

Thanks in advanced!!!

@DBuit
Copy link

DBuit commented Feb 1, 2017

@threesquared did you fix the error "No provider for ElementRef!" im having the same problem atm

@vishal41190
Copy link

vishal41190 commented May 16, 2017

@threesquared & @DBuit Did you fixed the issue with No provider for ElementRef! ?

@Skillnter
Copy link

Skillnter commented Jun 15, 2017

This is just creating tags but not getting/fetching tags if the tag is already present to update...

@bmxmaga
Copy link

bmxmaga commented Oct 24, 2017

@threesquared @DBuit @vishal41190 ElementRef is not relevant in scope of an Angular service. It would work only in a component.
You can just remove it from the constructor, as it's not even used at all.

@ishan123456789
Copy link

ishan123456789 commented Jul 1, 2018

Is'nt setDescription required as well?
I get this error as well I've added this service in my app.module providers list

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