Blog>
Snippets

Handling Redirections with Angular Universal for SEO

Showcase handling server-side redirections within an Angular Universal app to maintain SEO rankings by ensuring crawlers follow the correct paths.
import { Injectable } from '@angular/core';
import { Router } from '@angular/router';
import { RESPONSE } from '@nguniversal/express-engine/tokens';
import { Response } from 'express';

@Injectable({
  providedIn: 'root'
})
export class RedirectionService {
  constructor(
    private router: Router,
    @Inject(RESPONSE) private response: Response
  ) {}

  // Call this method to perform a server-side redirect
  redirectTo(url: string, statusCode: number = 301) {
    if (this.response) {
      // Set the HTTP status code for the response (e.g., 301 or 302)
      this.response.redirect(statusCode, url);
      this.response.end();
    } else {
      // Perform client-side navigation if response object is not available
      this.router.navigateByUrl(url);
    }
  }
}
RedirectionService is an injectable service within an Angular Universal application that handles server-side redirections. When the redirectTo method is called, it checks if the response object (from express) is available, meaning it's running server-side. If so, it performs a server-side redirect by setting the HTTP status code and redirect URL on the response object. If the response object is not available, it falls back to client-side navigation.
import { RedirectionService } from './path-to-redirection.service';

@Component({
  selector: 'app-some-component',
  template: '<p>Some Component</p>'
})
export class SomeComponent implements OnInit {
  constructor(private redirectionService: RedirectionService) {}

  ngOnInit() {
    // Example redirection usage within a component
    if (conditionForRedirection) {
      this.redirectionService.redirectTo('/new-url', 301);
    }
  }
}
This piece of code provides an example of using the RedirectionService within an Angular component. Inside the ngOnInit lifecycle hook, there's a conditional check to decide whether a redirection is necessary. If the condition is met, the redirectTo method on the RedirectionService is called with the new URL and the desired HTTP status code (301 for a permanent redirect).
server.get('*', (req, res) => {
  res.render(indexHtml, { req, providers: [{ provide: RESPONSE, useValue: res }] }, (err, html) => {
    // If there's a redirection, express has already handled it, so do not send the generated html
    if (!res.headersSent) {
      res.send(html);
    }
  });
});
In the Express server configuration for an Angular Universal app, we handle all GET requests with a wildcard. The 'res.render' method generates the server-side rendered page. The RESPONSE token is provided with the value of the current 'res' object, so any redirects set by the RedirectionService will be picked up by Express. After rendering, we check if the headers have already been sent as part of a redirect; if not, we send the generated HTML as a response.