Skip to content
svead

Advanced Patterns

Using @graph for Multiple Schemas

Combine multiple schema types using @graph:

Svelte
1<script lang="ts">
2	import { page } from '$app/state';
3	import {
4		Head,
5		SchemaOrg,
6		type SeoConfig,
7		type SchemaOrgProps,
8	} from 'svead';
9
10	const seo_config: SeoConfig = {
11		url: page.url.href,
12		title: 'Advanced Page with Multiple Schemas',
13		description: 'Example combining multiple schema types.',
14	};
15
16	// Create individual schema objects
17	const blog_posting = {
18		'@type': 'BlogPosting',
19		'@id': page.url.href,
20		headline: seo_config.title,
21		description: seo_config.description,
22		datePublished: '2023-08-22T10:00:00Z',
23		author: {
24			'@type': 'Person',
25			name: 'John Doe',
26		},
27	};
28
29	const breadcrumb_list = {
30		'@type': 'BreadcrumbList',
31		'@id': `${page.url.href}#breadcrumb`,
32		itemListElement: [
33			{
34				'@type': 'ListItem',
35				position: 1,
36				name: 'Home',
37				item: 'https://example.com',
38			},
39			{
40				'@type': 'ListItem',
41				position: 2,
42				name: seo_config.title,
43				item: page.url.href,
44			},
45		],
46	};
47
48	// Combine using @graph
49	const schema_org_config = {
50		'@context': 'https://schema.org',
51		'@graph': [blog_posting, breadcrumb_list],
52	};
53</script>
54
55<Head {seo_config} />
56<SchemaOrg schema={schema_org_config} />

Conditional Property Spreading

Use conditional spreading to include optional properties:

Svelte
1<script lang="ts">
2	import { page } from '$app/state';
3	import { SchemaOrg, type SchemaOrgProps } from 'svead';
4
5	const has_image = true;
6	const open_graph_image = 'https://example.com/image.jpg';
7	const website = 'https://example.com';
8
9	const schema_org: SchemaOrgProps['schema'] = {
10		'@type': 'WebPage',
11		'@id': page.url.href,
12		name: 'Page Title',
13		// Only include image if it exists
14		...(has_image &&
15			open_graph_image && {
16				primaryImageOfPage: {
17					'@type': 'ImageObject',
18					url: open_graph_image,
19				},
20			}),
21		// Conditionally add publisher
22		...(website && {
23			publisher: {
24				'@type': 'Organization',
25				name: 'Example Org',
26				url: website,
27			},
28		}),
29	};
30</script>
31
32<SchemaOrg schema={schema_org} />

Multiple SchemaOrg Components

You can use multiple SchemaOrg components on the same page:

Svelte
1<script lang="ts">
2	import { SchemaOrg, type SchemaOrgProps } from 'svead';
3
4	const website_schema: SchemaOrgProps['schema'] = {
5		'@type': 'WebSite',
6		'@id': 'https://example.com',
7		name: 'Example Site',
8	};
9
10	const article_schema: SchemaOrgProps['schema'] = {
11		'@type': 'Article',
12		'@id': 'https://example.com/article',
13		headline: 'Article Title',
14	};
15
16	const breadcrumb_schema: SchemaOrgProps['schema'] = {
17		'@type': 'BreadcrumbList',
18		itemListElement: [/* ... */],
19	};
20</script>
21
22<SchemaOrg schema={website_schema} />
23<SchemaOrg schema={article_schema} />
24<SchemaOrg schema={breadcrumb_schema} />

WebPage as Container with mainEntity

Use WebPage as a wrapper with mainEntity to indicate what the page is primarily about:

Svelte
1<script lang="ts">
2	import { page } from '$app/state';
3	import {
4		Head,
5		SchemaOrg,
6		type SeoConfig,
7		type SchemaOrgProps,
8	} from 'svead';
9
10	const seo_config: SeoConfig = {
11		url: page.url.href,
12		website: 'https://example.com',
13		title: 'My Blog Post',
14		description: 'An example blog post',
15		author_name: 'John Doe',
16	};
17
18	// WebPage wraps the main content
19	const schema_org: SchemaOrgProps['schema'] = {
20		'@type': 'WebPage',
21		'@id': page.url.href,
22		url: page.url.href,
23		name: seo_config.title,
24		description: seo_config.description,
25		isPartOf: {
26			'@type': 'WebSite',
27			'@id': seo_config.website,
28		},
29		// The page is primarily about this BlogPosting
30		mainEntity: {
31			'@type': 'BlogPosting',
32			'@id': `${page.url.href}#article`,
33			headline: seo_config.title,
34			description: seo_config.description,
35			datePublished: '2023-08-22T10:00:00Z',
36			author: {
37				'@type': 'Person',
38				name: seo_config.author_name,
39			},
40			publisher: {
41				'@type': 'Organization',
42				name: 'Example Blog',
43			},
44			mainEntityOfPage: {
45				'@type': 'WebPage',
46				'@id': page.url.href,
47			},
48		},
49	};
50</script>
51
52<Head {seo_config} />
53<SchemaOrg schema={schema_org} />

This pattern is useful when you want to provide both page-level and content-level metadata in a single schema object.

Adding potentialAction for Interactivity

Use potentialAction to indicate actions users can perform on the page:

Svelte
1<script lang="ts">
2	import { page } from '$app/state';
3	import { SchemaOrg, type SchemaOrgProps } from 'svead';
4
5	const schema_org: SchemaOrgProps['schema'] = {
6		'@type': 'WebPage',
7		'@id': page.url.href,
8		url: page.url.href,
9		name: 'Article Title',
10		// Indicates this page can be read
11		potentialAction: [
12			{
13				'@type': 'ReadAction',
14				target: [page.url.href],
15			},
16		],
17	};
18</script>
19
20<SchemaOrg schema={schema_org} />

This helps with:

  • Deep linking in mobile apps
  • Progressive Web App integration
  • Better understanding by search engines

Common action types:

  • ReadAction - For articles, blogs, documentation
  • WatchAction - For video content
  • ListenAction - For podcasts, audio
  • SearchAction - For search functionality
TypeScript
1// SearchAction example for site search
2const search_action_schema = {
3	'@type': 'WebSite',
4	url: 'https://example.com',
5	potentialAction: {
6		'@type': 'SearchAction',
7		target: {
8			'@type': 'EntryPoint',
9			urlTemplate:
10				'https://example.com/search?q={search_term_string}',
11		},
12		'query-input': 'required name=search_term_string',
13	},
14};
All documentation