/core

Dynamic page title & meta tags utility for Angular (w/server-side rendering)

Primary LanguageTypeScriptMIT LicenseMIT

@ngx-meta/core

Dynamic page title & meta tags generator for Angular

Linux build Windows build coverage npm version

Please support this project by simply putting a Github star. Share this library with friends on Twitter and everywhere else you can.

@ngx-meta/core updates the page title and meta tags every time the route changes, based on Angular app's route configuration.

  • When the Angular app uses server-side rendering, the meta tags and page titles generated by @ngx-meta/core successfully appear on HTML source, due to its platform-free workflow. This allows the SPA to be crawled and rendered by the search engines, as well as sharing the website link on social networks (facebook, twitter, etc).
  • It also supports resolving values using a callback function to use a custom logic on the meta tag contents (http-get, @ngx-translate/core, etc.).

NOTICE

If you're using @angular v4.x.x, use the latest release of v0.4.x (master branch).

If you're using @angular v2.x.x, use the latest release of v0.2.x (v0.2.x branch).

Table of contents:

Prerequisites

This package depends on @angular v4.0.0, and the master branch does no longer support @angular v2.x.x.

However, the v0.2.x branch keeps ongoing support for @angular v2.x.x - depending on @angular v2.0.0, and it's highly recommended that you are running at least @angular v2.4.0 and @angular/router v3.4.0. Older versions contain outdated dependencies, might produce errors.

  • If you're using @angular v4.x.x, use the latest release of v0.4.x (master branch).
  • If you're using @angular v2.x.x, use the latest release of v0.2.x (v0.2.x branch).

Also, please ensure that you are using Typescript v2.3.4 or higher.

Getting started

Installation

You can install @ngx-meta/core using npm

npm install @ngx-meta/core --save

Examples

  • ng-seed/universal and ng-seed/spa are officially maintained seed projects, showcasing common patterns and best practices for @ngx-meta/core.

Recommended packages

The following package(s) have no dependency for @ngx-meta/core, however may provide supplementary/shorthand functionality:

  • @ngx-config/core: provides meta settings from the application settings loaded during application initialization
  • @ngx-translate/core: provides internationalization (i18n) features to retrieve the translated meta settings

Adding @ngx-meta/core to your project (SystemJS)

Add map for @ngx-meta/core in your systemjs.config

'@ngx-meta/core': 'node_modules/@ngx-meta/core/bundles/core.umd.min.js'

Route configuration

Import MetaGuard using the mapping '@ngx-meta/core' and append canActivate: [MetaGuard] or canActivateChild: [MetaGuard] properties to the route definitions at app.routes (considering the app.routes is the route definitions in Angular application).

Then, add meta settings inside the data property of routes.

Note: meta properties such as title, description, author and publisher will be duplicated as og:title, og:description, og:author and og:publisher, so there's no need to declare them again in this context.

app.routes.ts

...
import { MetaGuard } from '@ngx-meta/core';
...
export const routes: Routes = [
  {
    path: '',
    canActivateChild: [MetaGuard],
    children: [
      {
        path: 'home',
        component: HomeComponent,
        data: {
          meta: {
            title: 'Sweet home',
            description: 'Home, home sweet home... and what?'
          }
        }
      },
      {
        path: 'duck',
        component: DuckComponent,
        data: {
          meta: {
            title: 'Rubber duckie',
            description: 'Have you seen my rubber duckie?'
          }
        }
      },
      {
        path: 'toothpaste',
        component: ToothpasteComponent,
        data: {
          meta: {
            title: 'Toothpaste',
            override: true, // prevents appending/prepending the application name to the title attribute
            description: 'Eating toothpaste is considered to be too healthy!'
          }
        }
      }
    ]
  }
  ...
];

app.module configuration

Import MetaModule using the mapping '@ngx-meta/core' and append MetaModule.forRoot({...}) within the imports property of app.module (considering the app.module is the core module in Angular application).

app.module.ts

...
import { MetaModule } from '@ngx-meta/core';
...

@NgModule({
  declarations: [
    AppComponent,
    ...
  ],
  ...
  imports: [
    ...
    RouterModule.forRoot(routes),
    MetaModule.forRoot()
  ],
  ...
  bootstrap: [AppComponent]
})

Settings

You can call the forRoot static method using the MetaStaticLoader. By default, it is configured to prepend page titles after the application name (if any set). These default meta settings are used when a route doesn't contain any meta settings in its data property.

You can customize this behavior (and ofc other settings) by supplying meta settings to MetaStaticLoader.

The following example shows the use of an exported function (instead of an inline function) for AoT compilation.

Setting up MetaModule to use MetaStaticLoader

app.module.ts

...
import { MetaModule, MetaLoader, MetaStaticLoader, PageTitlePositioning } from '@ngx-meta/core';
...

export function metaFactory(): MetaLoader {
  return new MetaStaticLoader({
    pageTitlePositioning: PageTitlePositioning.PrependPageTitle,
    pageTitleSeparator: ' - ',
    applicationName: 'Tour of (lazy/busy) heroes',
    defaults: {
      title: 'Mighty mighty mouse',
      description: 'Mighty Mouse is an animated superhero mouse character',
      'og:image': 'https://upload.wikimedia.org/wikipedia/commons/f/f8/superraton.jpg',
      'og:type': 'website',
      'og:locale': 'en_US',
      'og:locale:alternate': 'en_US,nl_NL,tr_TR'
    }
  });
}

...

@NgModule({
  declarations: [
    AppComponent,
    ...
  ],
  ...
  imports: [
    ...
    RouterModule.forRoot(routes),
    MetaModule.forRoot({
      provide: MetaLoader,
      useFactory: (metaFactory)
    })
  ],
  ...
  bootstrap: [AppComponent]
})

MetaStaticLoader has one parameter:

  • settings: MetaSettings : meta settings (by default, prepend page titles)

👍 Holy cow! @ngx-meta/core will update the page title and meta tags every time the route changes.

Using a callback function

The MetaStaticLoader accepts a callback function to use a custom logic on the meta tag contents (http-get, @ngx-translate/core, etc.).

Return type of the callback function must be string, Observable<string> or Promise<string>.

When a callback function is supplied, the MetaService will try to retrieve contents of meta tags (except og:locale and og:locale:alternate) using the specified callback. You can customize the behavior for missing/empty values, directly from the callback function itself.

app.module.ts

...
import { MetaModule, MetaLoader, MetaStaticLoader, PageTitlePositioning } from '@ngx-meta/core';
import { TranslateService } from '@ngx-translate/core';
...

export function metaFactory(translate: TranslateService): MetaLoader {
  return new MetaStaticLoader({
    callback: (key: string) => translate.get(key),
    pageTitlePositioning: PageTitlePositioning.PrependPageTitle,
    pageTitleSeparator: ' - ',
    applicationName: 'APP_NAME',
    defaults: {
      title: 'DEFAULT_TITLE',
      description: 'DEFAULT_DESC',
      'og:image': 'https://upload.wikimedia.org/wikipedia/commons/f/f8/superraton.jpg',
      'og:type': 'website',
      'og:locale': 'en_US',
      'og:locale:alternate': 'en_US,nl_NL,tr_TR'
    }
  });
}

...

@NgModule({
  declarations: [
    AppComponent,
    ...
  ],
  ...
  imports: [
    ...
    RouterModule.forRoot(routes),
    MetaModule.forRoot({
      provide: MetaLoader,
      useFactory: (metaFactory),
      deps: [TranslateService]
    })
  ],
  ...
  bootstrap: [AppComponent]
})

app.component.ts

...
import { MetaService } from '@ngx-meta/core';
...

@Component({
  ...
})
export class AppComponent implements OnInit {
  ...
  constructor(private readonly translate: TranslateService,
              private readonly meta: MetaService) { }

  ngOnInit(): void {
    // add available languages & set default language
    this.translate.addLangs(['en', 'tr']);
    this.translate.setDefaultLang(defaultLanguage.code);

    this.translate.use('en').subscribe(() => {
      this.meta.setTag('og:locale', 'en-US');
    });
  }
  ...
}

home.routes.ts

import { Routes } from '@angular/router';
import { HomeComponent } from './home.component';

export const routes: Routes = [
  {
    path: '',
    component: HomeComponent,
    data: {
      meta: {
        title: 'PUBLIC.HOME.PAGE_TITLE',
        description: 'PUBLIC.HOME.META_DESC'
      }
    }
  }
];

You can find out in-depth examples about the use of callback function on ng-seed/universal and on ng-seed/spa, which are officially maintained seed projects showcasing common patterns and best practices.

Set meta tags programmatically

...
import { Component, OnInit } from '@angular/core';
import { MetaService } from '@ngx-meta/core';
...

@Component({
  ...
})
export class ItemComponent implements OnInit {
  ...
  constructor(private readonly meta: MetaService) { }
  ...
  ngOnInit() {
    this.item = //HTTP GET for "item" in the repository
    this.meta.setTitle(`Page for ${this.item.name}`);
    this.meta.setTag('og:image', this.item.imageUrl);
  }
}

Credits

  • ng2-meta: Dynamic meta tags and SEO in Angular2

License

The MIT License (MIT)

Copyright (c) 2017 Burak Tasci