Dynamic Meta Tags in Angular: How I Built a Reusable SEO Service

When I rebuilt my portfolio with Angular SSG and hydration, one of my goals was to make every route fully optimized for SEO. That meant: unique titles, descriptions, Open Graph tags, Twitter tags, and clean indexing behavior for every page. Instead of manually setting metadata inside each component, I built a small reusable SeoService that updates all meta tags dynamically and works perfectly with Angular’s SSG output. This post covers how I built it, how it works, and how you can use the same pattern.

Why Dynamic Meta Tags Matter in SSG Angular Apps

Static Site Generation pre-renders your pages, which is awesome, but Angular still bootstraps on the client side. If parts of your site share routes, or if some metadata depends on content (like projects, blog posts, etc.), a reusable service keeps things tidy and avoids duplicated logic. Also, search engines expect properly structured metadata. Consistency helps your SEO score, click-through rate, and social previews. So one tiny service can make a surprisingly big difference.

Service Overview

Here’s how the full SeoService looks in my project before we break it down.

Screenshot of the Angular SeoService showing dynamic meta tag updates.
        
  export class SeoService {
    private title = inject(Title);
    private meta = inject(Meta);
    private doc = inject(DOCUMENT);
  
    setMetaTag(metaConfig: MetaConfig) {
      this.title.setTitle(metaConfig.title);
      this.meta.updateTag({
        name: 'description',
        content: metaConfig.description,
      });
      this.meta.updateTag({ name: 'author', content: metaConfig.author });
      this.meta.updateTag({ name: 'robots', content: metaConfig.robots });
  
      // Social sharing tags
      
      this.meta.updateTag({
        property: 'og:title',
        content: metaConfig.title,
      });
      this.meta.updateTag({
        property: 'og:description',
        content: metaConfig.description,
      });
      this.meta.updateTag({
        property: 'og:image',
        content: metaConfig.image,
      });
      this.meta.updateTag({
        property: 'og:image:width',
        content: metaConfig.width,
      });
      this.meta.updateTag({
        property: 'og:image:height',
        content: metaConfig.height,
      });
      this.meta.updateTag({
        property: 'og:url',
        content: metaConfig.url,
      });
    }
  }
 
      
This snippet is the real SEO gold. It covers:
  • title
  • Standard description tag
  • Open Graph tags
  • Optional keywords
  • Fallback image

It’s also easy to extend if you ever need canonical URLs, noindex rules, structured data, etc.

How Components Consume the Service

Most pages need their own metadata, so the pattern is simple:

Screenshot of an Angular component configuring and applying dynamic SEO meta tags.
        
  metaConfig: MetaConfig = {
     title: 'Patrick Linguerri | Angular Frontend Engineer',
     description:
       'Angular Engineer • Micro-Frontend Architect • Prototype Builder',
     author: 'Patrick Linguerri',
     robots: 'index, follow',
     image:
       'https://patricklinguerri.dev/patrick_linguerri_angular_frontendEngineer.webp',
     width: '1200',
     height: '630',
     url: 'https://patricklinguerri.dev/',
   };
   private seoService = inject(SeoService);
 
   ngOnInit(): void {
     this.seoService.setMetaTag(this.metaConfig);
 
      

This keeps all your SEO logic in one place while allowing every route to define its own metadata.

How the Service Interacts With Routes

diagram about SeoService cycle

Why This Works Well With SSG + Hydration

Since Angular pre-renders your pages, the initial HTML already ships with the right metadata. Then, during hydration, Angular takes over the DOM but preserves the < head> metadata unless you modify it. Because the service runs early in component initialization, it works seamlessly whether:
  • The page is loaded statically
  • The user navigates client-side
  • Or hydration kicks in

Everything stays consistent.

Patrick Linguerri

Angular Frontend Engineer