Skip to main content

SEO with Angular, add title, meta keywords, a must-do thing for your website


 

For those who don't know what SEO is, SEO stands for Search Engine Optimization, it helps people discover your site through search engines like Google, Bing, ...

Take a look at the below picture:


To let search engines discover your site, you must let search engines know your site, for google you can use Google Search Console but that's another topic, I assume search engines already know your site.

The 3 most important factors are URL, title tag, and meta tag (description, keyword,...). Search engines will look for those 3 things (and many other factors) to compare with the search query and decide whether your site is relevant or not.

Url
Try to use meaningful URLs. For example, instead of using a URL like https://yoursite.com/products/1
use https://yoursite.com/products/iphone or even better https://yoursite.com/iphone . You can achieve this by configuring your rooting modules.
To make slug URLs you can strip accents your product names and join them with a hyphen (-). For example:
Wireless Bluetooth Headphone -> wireless-bluetooth-headphone.
const routesRoutes = [
  {
    path: 'products/:slugUrl',
    component: ProductComponent
  }
];

Title & Meta tags

Unfortunately, if you are using Angular SPA (Single Page Application) all search engines except Google can not index (crawl) these tags because these tags are dynamically generated at the client-side (browsers) by javascript, so far only Google has an AJAX crawler which will wait a bit for javascript to generate dynamic HTML before they crawl. Google is the biggest search engine in the world so we are ok with this.

To add title and meta tags you can use Title and Meta services from @angular/platform-browser
If you get your items (e.g,.products, news, songs, blogs,...) from an API you can do something like this:

import { ComponentOnInit } from '@angular/core';
import { TitleMeta } from '@angular/platform-browser';

@Component({
  selector: 'app-product',
  templateUrl: './product.component.html',
  styleUrls: ['./product.component.scss']
})
export class ProductComponent implements OnInit  {
  productProduct;
  slugUrl = this.route.snapshot.paramMap.get('slugUrl');
  constructor(private routeActivatedRoute,
              private productServiceProductService,
              private titleServiceTitle,
              private metaServiceMeta) { }

  ngOnInit(): void {
    this.getProduct();
  }

  getProduct(): void {
    this.productService.get(this.slugUrl).subscribe(result => {
      this.product = result;
      const title = this.product.name;
      const tags = { name: 'keywords'content: this.product.tags};
      const description = { name: 'description'content: this.product.description};
      this.metaService.updateTag(tags);
      this.metaService.updateTag(description);
      this.titleService.setTitle(title);
    });
  }
}

You can also add/update these tags when navigating around your site by pre-configuring these data in your routing modules. I prefer to use both methods, you can pre-config these tags and when there are changes in your controllers (which always happen after navigating events) they will be updated.

In your routing module:

import { ProductListComponent } from './pages/product-list/product-list.component';
import { ProductComponent } from './pages/product/product.component';
import { NgModule } from '@angular/core';
import { RoutesRouterModule } from '@angular/router';


const routesRoutes = [
  {
    path: '',
    component: ProductListComponent,
    data: {
      title: "Products"
    }
  },
  {
    path: ':slugUrl',
    component: ProductComponent
  },
];

@NgModule({
  imports: [RouterModule.forChild(routes)],
  exports: [RouterModule]
})
export class ProductRoutingModule { }

In your app.component.ts

import { RouterNavigationEnd } from '@angular/router';
import { Component } from '@angular/core';
import { Title } from '@angular/platform-browser';
import { filtermap } from 'rxjs/operators';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  constructor(private routerRouter,
              private titleServiceTitle) {
    this.setSEOTags();
  }

  setSEOTags(): void {
    //listen for navigating events
    this.router.events
    .pipe(
      filter((event=> event instanceof NavigationEnd),
      map(() => this.router)
    )
    .subscribe((event=> {
        // look for titles in root module settings.
        const title = this.getTitle(this.router.routerStatethis.router.routerState.root).join(' - ') + ' - YourSiteName';
        this.titleService.setTitle(title);
      }
    );
  }

  getTitle(stateanyparentany): string[] {
    // get titles from parent and child roots.
    const data = [];
    if (parent && parent.snapshot.data && parent.snapshot.data.title) {
      const title = parent.snapshot.data.title;
      if (title) {
        data.push(title);
      }
    }

    if (state && parent) {
      data.push(... this.getTitle(statestate.firstChild(parent)));
    }
    return data;
  }
}

Above is an example of adding preset titles when navigating around your site.

In your index.html you should add your site title and description, later you can use metaService.updateTag(meta:description) since the tag has already existed.

Note that tags in your index.html are rendered in your server so all search engines can see it.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="keywords" content="keyword 1, keyword 2, keyword 3" />
    <meta name="description" content="Your site description" />
    <title>Your Site name</title>
    <base href="/">
    <meta name="referrer" content="strict-origin-when-cross-origin">
    <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
    <link rel="icon" type="image/x-icon" href="favicon.ico">
  </head>
  <body>
    <app-root></app-root>
  </body>
</html>

In some cases, Google might not be able to see data rendered on the client-side due to complex javascript, to check whether your SEO data can be seen by Google you can use Google URL Inspection Tool.

That's it for this guide, leave a  comment if you need my help, thanks for reading.

Comments

Popular posts from this blog

How to use Angular RouteReuseStrategy to create snapshots so you can back to previous pages without reloading data

Github of this  exmaple.  There are a lot of practical scenarios when you load a list of items then go to the detail of an item, when you hit the back button you don't want to reload the item list again. Angular provides you a method to do exactly that. With RouteReuseStrategy when you hit the back button it takes you right back to where you were before without reloading anything. Of course, you can choose to do this or not for any page and it super easy to set up. To do this you need to create a class implement RouteReuseStrategy from @angular/router. There are 5 methods you need to implement: shouldDetach, store, shouldAttach, retrieve, shouldReuseRoute. Let's take a closer look at these methods. shouldDetach shouldDetach ( route :  ActivatedRouteSnapshot ):  boolean When you go to the next page, this method will be trigged, it decides whether the current route (a page) should be detached. In other words, Angular takes a snapshot of it and saves it in memory ...

Create and deploy multi language (i18n) website with Angular 8+

This guide should work with Angular 8+.  In  this post: 1. Create an angular web project. 2. Set up i18n and translate. 3. Deploy the website on Windows using IIS. In this guide, I am using 2 languages, the setup for more than 2 languages should be similar. You can find the code of this guide in my github . 1. Create an angular web project. To create an angular app, in command  prompt type: ng new multiLanguageApp Open "app.component.html" delete the default code and paste this code : < div >    < a   href = "/" > de </ a > &nbsp;    < a   href = "/en" > en </ a > </ div > < div > Danke! </ div > Run "ng serve" to serve your app. Go to localhost:4200 you should see: I am creating an app with German as the default language and English as the second language. "Danke" is a word in German means "Thank you". When we click "de" or "en" in the UI to switch langu...