SEO Meta
SEO Meta can dynamically change page title, manage <meta>
tags, manage <html>
and <body>
DOM element attributes, add/remove/change <style>
and <script>
tags in the head of your document (useful for CDN stylesheets or for json-ld markup, for example), or manage <noscript>
tags
$useMeta
Zova provides the $useMeta
method in the BeanBase
base class, which can provide SEO Meta data
zova-dev/packages-zova/core/src/bean/beanBase.ts
typescript
export class BeanBase {
protected $useMeta(options: SSRMetaOptions | (() => SSRMetaOptions)) {}
}
1
2
3
2
3
zova-dev/packages-zova/core/src/types/interface/ssr.ts
typescript
export interface SSRMetaOptions {
title?: string;
titleTemplate?(title: string): string;
meta?: { [name: string]: SSRMetaTagOptions };
link?: { [name: string]: Record<string, string> };
script?: { [name: string]: Record<string, string> };
htmlAttr?: { [name: string]: string | undefined };
bodyAttr?: { [name: string]: string | undefined };
bodyStyle?: { [name: string]: string | undefined };
bodyClass?: { [name: string]: boolean };
noscript?: { [name: string]: string };
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
Static meta data
typescript
class ControllerPageSome extends BeanBase {
protected async __init__() {
const metaData = {
// sets document title
title: 'Index Page',
// optional; sets final title as "Index Page - My Website", useful for multiple level meta
titleTemplate: title => `${title} - My Website`,
// meta tags
meta: {
description: { name: 'description', content: 'Page 1' },
keywords: { name: 'keywords', content: 'Quasar website' },
equiv: { 'http-equiv': 'Content-Type', content: 'text/html; charset=UTF-8' },
// note: for Open Graph type metadata you will need to use SSR, to ensure page is rendered by the server
ogTitle: {
property: 'og:title',
// optional; similar to titleTemplate, but allows templating with other meta properties
template(ogTitle) {
return `${ogTitle} - My Website`;
},
},
},
// CSS tags
link: {
material: { rel: 'stylesheet', href: 'https://fonts.googleapis.com/icon?family=Material+Icons' },
},
// JS tags
script: {
ldJson: {
type: 'application/ld+json',
innerHTML: `{ "@context": "http://schema.org" }`,
},
},
// <html> attributes
htmlAttr: {
'xmlns:cc': 'http://creativecommons.org/ns#', // generates <html xmlns:cc="http://creativecommons.org/ns#">
empty: undefined, // generates <html empty>
},
// <body> attributes
bodyAttr: {
'action-scope': 'xyz', // generates <body action-scope="xyz">
empty: undefined, // generates <body empty>
},
// <noscript> tags
noscript: {
default: 'This is content for browsers with no JS (or disabled JS)',
},
};
this.$useMeta(metaData);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
Invoking $useMeta
multiple times will overwrite the value of the same key in the former:
typescript
// first loaded
class ControllerPageSome extends BeanBase {
protected async __init__() {
this.$useMeta({
title: 'Index Page',
});
}
}
// a subsequent loaded
class ControllerPageAnother extends BeanBase {
protected async __init__() {
this.$useMeta({
title: 'Index Page!!!',
});
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
Reactive meta data
$useMeta
also supports passing in reactive data:
typescript
class ControllerPageSome extends BeanBase {
title: string;
protected async __init__() {
this.$useMeta(() => {
return {
title: this.title,
};
});
}
setAnotherTitle() {
// will automatically trigger a Meta update due to the binding
this.title = 'Another title';
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16