GSD
Angular SEO: How to Make Search-Friendly Pages
Posted by Abhishek Kothari on October 6, 2023
The Angular framework is a structural javascript-based framework for web applications. It is used to create dynamic web pages with content rendered via web services. Angular is very developer-friendly and has been around for several years, accumulating a powerful community of tools and utilities, including Angular CMS tools, backend frameworks, and more.
JavaScript frameworks like Angular are constantly adapting and improving to keep up with the demands of the search engines and crawlers scouring the web. Maybe, you already use common SEO techniques, but the results could be better. Or perhaps, your current CMS isn't being updated as often as it should resulting in a dip in overall site performance.
The answer to your woes, however, could be a transition or upgrade to Angular Universal, a bundle created to make Angular applications more SEO-friendly. Version 11 and above of Angular include libraries allowing you to edit and execute meta tags. You can even configure Angular Universal to pre-render the data as it's starting up.
Applications built using the Angular framework are called Single Page Applications (SPAs) because of the way they function. An Angular application, once loaded, renders other pages dynamically without reloading the web pages all over again. This experience is delivered with the power of the Angular javascript framework. It dynamically modifies the pages by running javascript code or by loading only the required content. This gives the user a smooth experience without waiting for a reload to happen. However, Angular sites can suffer from adverse effects on their search engine optimization (SEO) from using the framework.
On your end, it's essential to code metadata so search engines will understand and process it effectively. Along with this task, there's also the need to beat out competitors who are doing the exact same thing.
In this article, we'll articulate how Angular applications need special SEO treatment, and we provide some specific deployment instructions to facilitate good Angular SEO.
Table of contents
Understanding search engine crawlers and SEO
Before we address the solution, let us understand how the search engine crawlers (or bots) actually work. Search engines around the world crawl through your websites to understand the pages and the end goal of your business. For this, the crawlers read through the metadata of the pages such as the title, description, image tags, and categories. This metadata needs to be different for every page to allow search engines to understand each page's intent.
A search engine bot reaches a specific page, finds the hyperlinks on the page, reads the metadata on the page, and starts traversing through the hyperlinks. It keeps repeating this process on your website until it is unable to find any new links. During this process, the bot downloads the static content of your website and understands the page. Thus, it becomes important to maximize the details of each page in the metadata and static content.
Most pitfalls in regards to SEO are related to the fact that not all search engines work the same way. Bing, Yahoo, and some lesser-known engines like DuckDuckGo do not work effectively with Angular's standard rendering process, meaning that your URLs won't receive the indexing you need in order to rank.
The first thing to load when your app runs is the HTML shell, a script written to render and populate the specified content. The unique metadata inside your pages isn't accessed by the client's browser or any crawlers until after the JavaScript is rendered. This lag strongly affects the effectiveness and efficiency of the SEO techniques you've integrated. The same goes for social media bots that collect summary cards for display inside their interfaces. Switching from standard rendering to server-side rendering can help solve this issue. However, the main pitfall here that we are correcting is Angular’s standard rendering process.
If Google is the only search engine you care about, you still don't have a solid guarantee that standard JS-rendered content will be effective because any kind of third-party software can interfere. If you use on-page actions, for example, Googlebot can be tripped up and slowed down. The same goes for elaborate JS code Google considers too "expensive" to run. These obstacles can cause your content to slow down.
SEO for conventional web applications
SEO has become one of the most important investments for any online business today. In the past, the web applications being developed were fairly simple and contained mostly static pages. These pages contained all the required information pre-coded into them. As web application development evolved, we entered an era of dynamic content rendering where the content for the web pages is stored somewhere and fetched as needed.
There are several ways to do this:
Server-side rendering (SSR)
To reduce the number of server requests and round trips for data collecting and templating on the client side some turn to SSR. Server-side rendering means that an application has the ability to convert HTML files on the server into fully rendered HTML pages for the client. First, the web browser submits a request for information from the server, then the server instantly responds by sending a fully rendered page to the client.
Partial indexing and missing content are very unlikely to occur with SSR. Unlike client-side rendering, SSR has fewer crawl-budget-related SEO and page speed issues. One of the major drawbacks of SSR is that third-party JavaScript rarely functions with it.
Client-side rendering (CSR)
Content is rendered in the browser, not the site's server when using client-side rendering. This is the rendering method that is used by default when using a JavaScript framework.
Because it lowers the server load, it's the most dependable and scalable method to offer dynamic webpages for the website owner. This adds milliseconds to seconds to the load time, which can result in longer than desired wait times for users. As resources become accessible, search bots must return to the site to render the JavaScript. This second wave of indexing may take a long time.
Dynamic Rendering (DR)
Dynamic rendering means that you are sending content generated on the client-side to the user and rendering the content generated on the server-side, i.e. the HTML files to the bots, who will produce the HTML pages and the content seen by the user. One of its benefits is that crawling and indexing your content is possible without the requirement for Google to run JavaScript. Another advantage is that re-rendering content for humans and bots saves developers time and resources. It also solves problems with the crawl budget that is linked to page speed. Google can crawl more pages on the site this way. However, interactive features that need JavaScript are still beneficial to human visitors.
One drawback of dynamic rendering, however, is the need to monitor for unwanted discrepancies between the user experience and the SSR version of each page.
While each method has its downside, keep in mind that other factors will affect speed and response. The specific hosting service, bandwidth, location, and device you use will also have an effect on speed and performance. Assess the quantity of your content, the power of your equipment and staff, and your traffic level in order to determine which rendering method is best for your unique situation.
Due to the lack of sophisticated client-side rendering frameworks in the past, server-side rendering of pages was the trend. There were numerous languages and frameworks to handle the same. For instance, PHP, Java, Spring, NodeJS with Handlebars, and other frameworks render the pages in advance and send only the plain HTML content to the frontend.
This approach ensures that the page has the right meta tags and all the content rendered before it is received by the search engine crawler. Thus, conventional web applications were practically simple when it came to SEO. However, they surely had a downside of longer loading times. With low-end servers, processing thousands of requests for pages became difficult. This brought frontend frameworks like Angular into the picture.
SEO for Single Page Applications (SPAs)
A single page application is a concept where the application base layout is loaded only once and the rest of the pages and components are loaded only as needed. This is made possible with the power of Javascript that dynamically decides what content is required, fetches the data, and renders it in the desired format.
Benefits of a single page application
Due to its dynamic nature, a single page application has a lot of inherent benefits associated with it. Some of these are listed below:
- Faster transition time once the application has loaded
- Smoother experiences compared to a conventional web application
- Less load on the webserver processing the pages
- Faster development time with sophisticated frameworks like Angular
Despite these benefits, one significant challenge with single page applications is SEO.
Angular SEO challenges
As understood, Angular does not reload the pages unless explicitly asked to. Angular does support change of metadata for the pages dynamically but it completely depends on JavaScript. As discussed before, search engine crawlers do not normally entertain Javascript. This can cause Angular applications to fail in rendering the right content or metadata.
However, over the years, Angular SEO has evolved and the community has brought a solution to get around this. The solution allows us to create static pages out of Angular pages. These static pages contain the right metadata and pre-rendered content. Later in this article, we will dive into this process to understand the challenges involved and implement tactics to optimize Angular SEO.
Angular SEO: Developing search-friendly pages
Before we begin building a working Angular SEO solution, let us start by creating a blank Angular JS application.
ng new seo-friendly-app
The command creates a fresh Angular JS application where we will create a simple home page and blog page, render some content on the blog page using ButterCMS APIs and make them SEO-friendly.
Let’s start by creating pages and routes for the same. Execute the below commands in the terminal to create your home and blog pages.
ng g c pages/home --skipTests=true
ng g c pages/blog --skipTests=true
This will create the components and import them into the app.module.ts file. Now, add the pages to the routing module to allow us to route to these pages. Modify your app-routing.module.ts file.
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { HomeComponent } from './pages/home/home.component';
import { BlogComponent } from './pages/blog/blog.component';
const routes: Routes = [
{
path: 'home',
component: HomeComponent
},
{
path:'blog',
component: BlogComponent
},
{
path:'**',
component: HomeComponent
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
The above code maps the respective components with their routes and sets HomeComponent
as the default component. Now, modify the app.component.html file to contain only a single line of code.
<router-outlet></router-outlet>
Finally, run the application using the below command and check to ensure that your application is set up correctly. Once the command goes through, you can hit the URL localhost:4200 to ensure things are set up fine. You should see the text “home works!”.
ng serve
Now let us add a header that allows us to navigate through the pages. Create a header component using the below command.
ng g c header --skipTests=true
Next, modify the content of the header.component.html to contain the navigation elements.
<div>
<a [routerLink]="['home']">Home</a>
</div><div>
<a [routerLink]="['blog']">Blog</a>
</div>
Finally, you have a complete application where you have two pages and a simple unstyled navigation that allows you to move between the pages. Now, let us analyze this application from an SEO perspective. Right-click on the browser and select “View page source”. You should be able to see how the search engine crawlers would see your page without Javascript. The code looks like the below snippet.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>SeoFriendlyApp</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<script src="runtime.js" type="module"></script><script src="polyfills.js" type="module"></script><script src="styles.js" type="module"></script><script src="vendor.js" type="module"></script><script src="main.js" type="module"></script></body>
</html>
Now, navigate to the blog page and perform the same action and notice the page content. It is similar. This includes the page title as well as body. This is because Angular modifies your DOM using javascript.
Creating dynamic pages
Hereby, we managed to implement this on the static pages. Let us now render our blogs and blog content page using ButterCMS API. This will allow us to perform SEO on static as well as dynamic web content. Before starting with it, do register a free trial account with ButterCMS to be able to create dynamic content easily.
To do this, let’s install ButterCMS plugin using NPM.
npm install --save buttercms
Once installed, let’s create a service file on the path services/butterCMS.service.ts and put in the below content inside the file.
import * as Butter from 'buttercms';
export const butterService = Butter('your_api_token');
Replace your token in the above code. This service file ensures that the token is managed globally in a single file. We can import this file wherever we need to use the ButterCMS services. Now, let us quickly implement the below code in the blog.component.ts file to get a list of posts.
import { Component, OnInit } from '@angular/core';
import { butterService } from '../../services/butter-cms.service';
@Component({
selector: 'app-blog',
templateUrl: './blog.component.html',
styleUrls: ['./blog.component.css']
})
export class BlogComponent implements OnInit {
posts:any[];
constructor() {
this.fetchPosts();
}
private fetchPosts() {
butterService.post.list({
page: 1,
page_size: 10
})
.then((res) => {
console.log('Content from ButterCMS');
console.log(res);
this.posts = res.data.data;
});
}
ngOnInit() {
}
}
Now, go to the browser and inspect the console output in the console. You should be able to see the list of your posts in the browser console. As you can see in the code snippet below, this demonstrates two of the posts that I have created for this tutorial.
Now, let us render this content on the blog page. To do so, update your blog.component.html file with the below code:
<div *ngIf="posts!=undefined">
<div *ngFor="let post of posts.data">
<hr>
<h1>{{post.title}}</h1>
<div [innerHTML]="post.body"></div>
</div>
</div>
This will render the posts from your ButterCMS platform onto the webpage. Let us now understand how to set a custom title and meta tags for each page.
Setting title and meta tags for Angular SEO
Angular understands this problem and already has a solution to this. To add metadata and modify the page title dynamically, all you need to do is utilize these modules from Angular. Update the code for your home.component.ts file with the below. Perform similar changes on your blog.component.ts as well.
import { Component, OnInit } from '@angular/core';
import { Meta,Title } from '@angular/platform-browser';
@Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor(private meta: Meta,private title: Title) {
this.meta.addTags([
{name: 'description', content: 'Home page of SEO friendly app'},
{name: 'author', content: 'buttercms'},
{name: 'keywords', content: 'Angular, ButterCMS'}
]);
this.setTitle('Home Page');
}
public setTitle( newTitle: string) {
this.title.setTitle( newTitle );
}
ngOnInit() {
}
}
Once these changes are saved, observe the title on the browser tab. It changes dynamically as you navigate through pages. Additionally, if you inspect the code in the browser console you will see that the corresponding metadata has also been attached. However, if you check the page source the content is still the same. This means that if Javascript is permitted, we can generate a dynamic title and meta, but not without it.
Thus, we need a way to take the content of this rendered page and send it to the user. This process is called pre-rendering of the content, and it is critical to achieving good Angular SEO. There are several methods to perform pre-rendering. In the next section, we will explore one of them.
Understanding the need for pre-rendering
Pre-rendering essentially means that the HTML content of the page would be compiled in advance. This would ensure that the title and metadata of the page is present when it reaches the client-side. With pre-rendering, we can expose the final HTML content to the crawler rather than exposing blank HTML.
How Angular Universal helps
Angular Universal as a pre-rendering solution for Angular that can be utilized right from the start of building your app or it can be integrated into an already-existing app. You can also use the Universal Bundle to create client-side rendering at the same time.
A successful project works like this: Angular grabs the server-side page to use for the initial browser result when a request hits your server. The dynamic client-side content is processed and soon replaces the static code. The app keeps on running client mode during the user session. This allows clients to interact with content quickly and flawlessly, without slow lags or reloads.
Implementing pre-rendering for Angular applications
With the upgrades in Angular, now it comes with a standardized solution to pre-rendering as well. The process is quite simple. We would leverage the Angular Universal package to support pre-rendering of the pages. To add the Angular universal package, execute the below command with the project name that you used while creating your Angular app.
ng add @nguniversal/express-engine --clientProject seo-friendly-app
This will create some files within the project and configure your project to support pre-rendering using a NodeJS server. In order to run this, execute the below command.
npm run build:ssr && npm run serve:ssr
This command compiles, builds your static pages, places them in the dist folder and serves them by running a NodeJS server. With this, we have greatly improved our Angular SEO by ensuring that our application is built in an SEO-friendly manner and all its content is dynamically rendered.
Validating your SEO-friendly Angular SPA
To validate the implementation, you can go to the browser and view page source for each page. Now, you will be able to see that the browser renders the exact HTML content as you would expect it to. With this, we established our implementation of a simple unstyled blog with an SEO-friendly rendering on Angular framework. With ButterCMS, you can do a lot more like dynamically fetching the SEO tags, meta descriptions, and even the page content itself. Check out our Angular API documentation to learn more.
ButterCMS is the #1 rated Headless CMS
Related articles
Don’t miss a single post
Get our latest articles, stay updated!
Abhishek is a software solution architect with 6+ years of experience in the industry. He has had opportunities to build and architect numerous small to large web applications and platforms leveraging various Cloud services and platforms. He also really enjoys sharing knowledge with the community by writing blogs, conducting training and building engaging courses.