Skip to content

Commit 6359696

Browse files
authored
Feature(SEO): Dynamic meta tag support (#200)
Description: Added dynamic description tags and a `noindex` metatag to stop web crawlers from indexing our 404 pages. Features: * When going to pages that exist, meta tags descriptions are added to the head for better descriptions on search engine results * When hitting a 404, the meta tag `<meta name="robots" content="noindex">` is added, so that old pages that don't exist aren't indexed by search engines.
1 parent 0e6c1f0 commit 6359696

File tree

2 files changed

+80
-13
lines changed

2 files changed

+80
-13
lines changed

src/app/app.component.ts

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
1-
/* eslint-disable @typescript-eslint/no-extraneous-class */
2-
import { ChangeDetectionStrategy, Component } from '@angular/core';
3-
import { RouterOutlet } from '@angular/router';
1+
import { ChangeDetectionStrategy, Component, inject, OnInit } from '@angular/core';
2+
import { Meta } from '@angular/platform-browser';
3+
import { ActivatedRoute, Data, NavigationEnd, Router, RouterOutlet } from '@angular/router';
44
import { NavBarComponent } from 'components/nav-bar/nav-bar.component';
55
import { TabBarComponent } from 'components/tab-bar/tab-bar.component';
6+
import { of } from 'rxjs';
7+
import { filter, map, mergeMap } from 'rxjs/operators';
8+
9+
const DEFAULT_DESCRIPTION =
10+
"Site dedicated to and maintained by SFU's Computing Science Student Society";
611

712
@Component({
813
selector: 'app-root',
@@ -11,4 +16,39 @@ import { TabBarComponent } from 'components/tab-bar/tab-bar.component';
1116
styleUrl: './app.component.scss',
1217
changeDetection: ChangeDetectionStrategy.OnPush
1318
})
14-
export class AppComponent {}
19+
export class AppComponent implements OnInit {
20+
private router = inject(Router);
21+
private route = inject(ActivatedRoute);
22+
private metaService = inject(Meta);
23+
24+
ngOnInit(): void {
25+
this.router.events
26+
.pipe(
27+
filter(event => event instanceof NavigationEnd),
28+
map(() => {
29+
let route = this.route.firstChild;
30+
while (route?.firstChild) {
31+
route = route.firstChild;
32+
}
33+
return route;
34+
}),
35+
filter(route => route?.outlet === 'primary'),
36+
mergeMap(route => route?.data ?? of({} as Data))
37+
)
38+
.subscribe(data => {
39+
if (data['meta']) {
40+
this.metaService.updateTag({
41+
name: 'robots',
42+
content: 'noindex'
43+
});
44+
} else {
45+
this.metaService.removeTag("name='robots'");
46+
}
47+
const desc = data['description'] ?? DEFAULT_DESCRIPTION;
48+
this.metaService.updateTag({
49+
name: 'description',
50+
content: desc
51+
});
52+
});
53+
}
54+
}

src/app/app.routes.ts

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,58 +15,85 @@ export const routes: Routes = [
1515
{
1616
path: 'readme',
1717
loadComponent: () => import('./pages/readme/readme.component').then(m => m.ReadMeComponent),
18-
title: makeTitle('README')
18+
title: makeTitle('README'),
19+
data: {
20+
description: 'Welcome to the Computing Science Student Society!'
21+
}
1922
},
2023
{
2124
path: 'officers',
2225
loadComponent: () =>
2326
import('./pages/officers/officers.component').then(m => m.OfficersComponent),
24-
title: makeTitle('Officers')
27+
title: makeTitle('Officers'),
28+
data: {
29+
description: 'Meet the officers that keep the CSSS running.'
30+
}
2531
},
2632
{
2733
path: 'committees',
2834
loadComponent: () =>
2935
import('./pages/committees/committees.component').then(m => m.CommitteesComponent),
30-
title: makeTitle('Committees')
36+
title: makeTitle('Committees'),
37+
data: {
38+
description: 'Learn about the committees that make up the CSSS.'
39+
}
3140
},
3241
{
3342
path: 'common-room',
3443
loadComponent: () =>
3544
import('./pages/common-room/common-room.component').then(m => m.CommonRoomComponent),
36-
title: makeTitle('Common Room')
45+
title: makeTitle('Common Room'),
46+
data: {
47+
description: 'Come hang out with us in the Common Room.'
48+
}
3749
},
3850
{
3951
path: 'affiliates',
4052
loadComponent: () =>
4153
import('./pages/affiliates/affiliates.component').then(m => m.AffiliatesComponent),
42-
title: makeTitle('Affiliates')
54+
title: makeTitle('Affiliates'),
55+
data: {
56+
description: 'Find out about other societies and clubs that our members interact with'
57+
}
4358
},
4459
// Events
4560
{
4661
path: 'events',
4762
loadComponent: () => import('./pages/events/events.component').then(m => m.EventsComponent),
48-
title: makeTitle('Events')
63+
title: makeTitle('Events'),
64+
data: {
65+
description: 'Discover the events the CSSS hosts.'
66+
}
4967
},
5068
{
5169
path: 'event-archives',
5270
loadComponent: () =>
5371
import('pages/event-archives/event-archives.component').then(m => m.EventArchivesComponent),
54-
title: makeTitle('Event Archives')
72+
title: makeTitle('Event Archives'),
73+
data: {
74+
description: 'Explore the old event pages past executive teams created.'
75+
}
5576
},
5677
// Elections
5778
{
5879
path: 'elections',
5980
loadComponent: () =>
6081
import('./pages/elections/elections.component').then(m => m.ElectionsComponent),
61-
title: makeTitle('Elections')
82+
title: makeTitle('Elections'),
83+
data: {
84+
description: 'Learn about the responsibilities of our executives and how you can become one.'
85+
}
6286
},
6387
{ path: '', component: HomeComponent, title: 'Computing Science Student Society' },
6488
// 404 will go down there
6589
{
6690
path: '**',
6791
loadComponent: () =>
6892
import('./pages/not-found/not-found.component').then(m => m.NotFoundComponent),
69-
title: makeTitle('Not Found')
93+
title: makeTitle('Not Found'),
94+
data: {
95+
meta: 'noindex'
96+
}
7097
}
7198
] as const;
7299

0 commit comments

Comments
 (0)