Opens an external site in a new window
Mental Health Awareness Month
“Community”
RODNEY LAB
  • Home
  • Plus +
  • Newsletter
  • Links
  • Profile
RODNEY LAB
  • Home
  • Plus +
  • Newsletter
  • Links

SvelteKit FAQ Page SEO: add JSON‑LD Schema # SvelteKit FAQ Page SEO: add JSON-LD Schema #

blurry low resolution placeholder image SvelteKit FAQ Page SEO
  1. Home Rodney Lab Home
  2. Blog Posts Rodney Lab Blog Posts
  3. SvelteKit SvelteKit Blog Posts
<PREVIOUS POST
NEXT POST >
LATEST POST >>

SvelteKit FAQ Page SEO: add JSON‑LD Schema #

Updated 4 months ago
10 minute read
Gunning Fog Index: 7.5
2 comments
Content by Rodney
blurry low resolution placeholder image Author Image: Rodney from Rodney Lab
SHARE:

🔑 Creating an FAQ Page with SEO Metadata in SvelteKit #

In this article on SvelteKit FAQ Page SEO, we see how easy SvelteKit makes it to create an FAQ page. As well as that, we generate search engine optimized metadata. This is the stuff that increases user experience on search engine result pages and so is loved by Google, meaning your page will rank higher.

Frequently asked question (FAQ) pages are helpful when you are looking for a quick solution to a current issue, and you don't want to have to read through reams of docs to extract the snippet you need. As an extra step when you create an FAQ page, it is worth also creating some metadata which tells Google about the questions and answers on the page. This is because user interaction (on the search results page) is an important ranking factor, meaning your page will appear higher in search results. In this article we see how you can add the right markup to your FAQ page in SvelteKit. I hope you will find the code useful and try it out on a suitable project that you are working on.

🌟 Our Goal: FAQ Featured Snippet #

blurry low resolution placeholder image SvelteKit FAQ Page SEO: image search Google result page for the query What is narcissus backendless.  At the top of the results is a paragraph  of text as a feature snippet directly answering this question.
SvelteKit FAQ Page SEO: Google Featured Snippet

FAQ metadata on your page will prove especially useful to users who form their search query as a question. Supporting this type of search becomes increasingly import as search using mobile devices and electronic personal assistants (the likes of Alexa, Siri and friends) becomes more widespread. For example, we see in the capture above of a desktop Google search, the top result is a featured snippet. Featured snippets may also take the form of a How To. They appear large, above all results and most of all; users like to click them.

blurry low resolution placeholder image SvelteKit FAQ Page SEO: How To Example capture shows Google search results to query Create Svelte Kit component library.  The top result dominates, listing 6 of the 10 steps needed to Create a SvelteKit Component Library.
SvelteKit FAQ Page SEO: Google Featured Snippet: How To Example

Google will experiment with shuffling up search results and throwing your page to the top. If it does not get enough interaction, though, it can quickly lose that prime position. It is important to remember that most users will not look beyond the first few results. So the top spaces are extremely valuable for getting users to your site.

Next, we will take a peek at the SvelteKit FAQ page we are going to build featuring the meta needed for it to be considered for a featured snippet.

🧱 SvelteKit FAQ Page SEO: What we’re Building #

We will create a single page app. This builds on the earlier SEO tutorials where we saw how to add basic SEO metadata for search engine optimization in SvelteKit, sharing cards for social networks and next level Schema.org SEO meta to delight search engine users and get them onto your site.

blurry low resolution placeholder image SvelteKit FAQ Page SEO: Image shows an F A Q page with the first question expanded, and another two question collapsed.
SvelteKit FAQ Page SEO: What we are Building

We will source our question data from a JSON file so that we can take advantage of SvelteKit JSON data imports. Once we have built the site, we will see how you can test it with Google's own SEO tools.

⚙️ SvelteKit FAQ Page SEO: Setting up the Project #

To get going, spin up a skeleton SvelteKit project:

    
pnpm dlx sv create sveltekit-faq-page-seo && cd $_
pnpm install

You can answer no to the TypeScript prompt but, select ESLint and prettier formatting. Next, we just need a couple of extra packages for this project:

    
pnpm add -D @fontsource/dm-sans dotenv

Then let's create a .env file in the project's root directory:

.env
plaintext
    
VITE_SITE_URL=https://example.com

Add the URL where you will deploy the site, or just keep example.com for now, if you are not yet sure what this will be. Finally, add a build time variable to vite.config.js

vite.config.js
javascript
    
1 import { sveltekit } from '@sveltejs/kit/vite';
2
3 /** @type {import('vite').UserConfig} */
4 const config = {
5 plugins: [sveltekit()],
6 define: {
7 'process.env.VITE_BUILD_TIME': JSON.stringify(new Date().toISOString()),
8 },
9 };
10
11 export default config;

The code in line 10 lets us get build time for use in the SEO meta.

⚙️ SvelteKit FAQ Page SEO: Questions #

It wouldn't be much of an FAQ page without some questions, so let's create a src/lib/data folder and put an faqs.json file in there. We will import the data directly into our Svelte markup. If you want to learn more about how this works, there is a tutorial which cover s a couple of different data shapes. Anyway, either paste in these questions, or add your own, keeping the same structure:

src/lib/data/faqs.json
json
    
1 [
2 {
3 "question": "What is the deal with SvelteKit?",
4 "answer": "SvelteKit is an awesome tool for building fast websites and web apps. Its secret powers lie in the compiler at Svelte's heart. This lets Svelte generate pure JavaScript which is interpreted by the user browser. This is contrast to other frameworks where an additional step of generating JavaScript in the browser is required. SvelteKit is to Svelte what Next is to React, it is a tool for creating Svelte apps."
5 },
6 {
7 "question": "Is SvelteKit ready for production?",
8 "answer": "SvelteKit is already used in a number of production website globally."
9 },
10 {
11 "question": "Does SvelteKit use Vite?",
12 "answer": "Yes. Vite is a next generation bundler, building on advances earlier made by more established tools like WebPack. Among the advantages are faster hot module reloading and better tree shaking. These benefits come from using ES Modules."
13 },
14 {
15 "question": "Is SvelteKit still in beta?",
16 "answer": "Yes, SvelteKit is still in beta. Despite that it is already used in a number of production websites."
17 },
18 {
19 "question": "How do you deploy SvelteKit?",
20 "answer": "You can deploy SvelteKit apps as static sites or Server Side Rendered apps. Leading hosting services like Cloudflare, Netlify, Render and Vercel all support SvelteKit."
21 }
22 ]

You will need at least three questions for Google to consider the page to be a valid FAQ page.

🏠 SvelteKit FAQ Page SEO: Home Page #

You'll see the Svelte markup is going to be quite lightweight, making it easier for you to rip this code out and insert it as a component or page in your own project. For that reason, the FAQ aspects of SEO are fully working and tested, but the rest of SEO is not fully fleshed out. Replace the code in src/routes/+page.svelte:

src/routes/+page.svelte
svelte
    
1 <script>
2 import Question from '$lib/components/Question.svelte';
3 import SEO from '$lib/components/SEO.svelte';
4 import website from '$lib/configuration/website';
5 import faqs from '$lib/data/faqs.json';
6 import '@fontsource/dm-sans';
7 import '$lib/styles/global.css';
8
9 const { siteUrl } = website;
10 const title = 'SvelteKit FAQ Page with SEO';
11 const url = `${siteUrl}`;
12 </script>
13
14 <SEO
15 {url}
16 {title}
17 {faqCount}
18 seoMetaDescription="Demo site for FAQ page using SvelteKit with SchemaOrg FAQ metadata"
19 />
20 <main class="container">
21 <div class="content">
22 <h1>SvelteKit FAQs</h1>
23 <section role="feed">
24 {#each faqs as { question, answer }, index}
25 <article aria-posinset={index + 1} aria-setsize={faqCount}>
26 <Question id={`question-${index + 1}`} {question} {answer} position={index + 1} {url} />
27 </article>
28 {/each}
29 </section>
30 </div>
31 </main>

If you’re not new to these tutorials, you can skip to the next paragraph. Vite lets us import our JSON file and use it in the JavaScript code. You will notice the JSON file has an array at the top level, and so the import in line 5 results in faqs holding that array. We can treat this just like any other array in JavaScript. In lines 23 – 27 we iterate over the elements of the array, producing a question for each one. If you are more familiar with React, consider this analogous to an array.map() method, though in Svelte there is no need to add a key to each element. Let's look at the first line of the each block. Recall, each element of the array is an object with a question and answer field. We can destructure those fields from each element and also access the index using the concise notation in line 23.

This code doesn’t yet work… we will define the missing SEO and Question components next. Before that, here is some optional styling which you can paste at the bottom of the same file:

src/routes/+page.svelte — click to expand code.
src/routes/+page.svelte
svelte
    
<style>
.container {
display: flex;
min-height: 100vh;
width: 100%;
}
.content {
display: flex;
flex-direction: column;
margin: var(--spacing-4) var(--spacing-4) var(--spacing-8);
width: 100%;
}
@media (min-width: 768px) {
:global(h1) {
font-size: var(--font-size-7);
}
.content {
margin: var(--spacing-8) var(--spacing-20) var(--spacing-12);
}
}
</style>

Then add global styles in a new src/lib/styles/global.css file:

src/lib/styles/global.css — click to expand code.
src/lib/styles/global.css
css
    
html {
background-image: linear-gradient(
to bottom right,
hsl(var(--colour-dark-hue) var(--colour-dark-saturation) var(--colour-dark-luminance)),
hsl(
var(--colour-dark-hue) var(--colour-dark-saturation) calc(var(--colour-dark-luminance) * 0.8)
)
);
color: hsl(var(--colour-light-hue) var(--colour-light-saturation) var(--colour-light-luminance));
font-family: DM Sans;
}
h1 {
font-size: var(--font-size-7);
margin-top: var(--spacing-0);
margin-bottom: var(--spacing-2);
}
:root {
/* paradise pink */
--colour-brand-hue: 345;
--colour-brand-saturation: 76%;
--colour-brand-luminance: 58%;
/* coral */
--colour-alt-hue: 14;
--colour-alt-saturation: 100%;
--colour-alt-luminance: 70%;
/* charleston green */
--colour-dark-hue: 120;
--colour-dark-saturation: 1%;
--colour-dark-luminance: 17%;
/* nickel */
--colour-mid-hue: 44;
--colour-mid-saturation: 7%;
--colour-mid-luminance: 41%;
/* eggshell */
--colour-light-hue: 49;
--colour-light-saturation: 60%;
--colour-light-luminance: 93%;
--spacing-0: 0;
--spacing-2: 0.5rem;
--spacing-4: 1rem;
--spacing-8: 2rem;
--spacing-12: 3rem;
--spacing-20: 5rem;
--font-size-1: 1rem;
--font-size-2: 1.25rem;
--font-size-7: 3.815rem;
--font-weight-medium: 500;
--line-height-relaxed: 1.75;
}

😕 SvelteKit FAQ Page SEO: Question Component #

Svelte (like Astro) lets us directly add elements to the HTML head section without the need for something like React Helmet. You will see again that the code ends up being quite lightweight. Create a src/lib/components folder and add a Question.svelte file with the following content:

src/lib/components/Question.svelte
svelte
    
<script>
let { question, answer, position, id, url, language = 'en-GB' } = $props();
const schemaOrgQuestionObject = {
'@context': 'https://schema.org',
'@type': 'Question',
'@id': `${url}#${id}`,
position,
url: `${url}#${id}`,
name: question,
answerCount: 1,
acceptedAnswer: {
'@type': 'Answer',
text: answer,
inLanguage: language,
},
inLanguage: language,
};
let jsonLdString = JSON.stringify(schemaOrgQuestionObject);
let jsonLdScript = `
<script type="application/ld+json">
${jsonLdString}
${'<'}/script>
`;
</script>
<svelte:head>
{@html jsonLdScript}
</svelte:head>
<section class="container">
<details {id} class="question">
<summary class="summary">{question}</summary>
<div class="answer">
<p>
{answer}
</p>
</div>
</details>
</section>

In lines 9 – 29, we construct the JSON-LD metadata object. This converts our questions and answers into a form which Google and other search engines can easily interpret. It follows the Schema.org Question  structured data pattern. We build up a JSON object and then place it into a script tag in lines 26 – 28. The code in line 28 is just a workaround to ensure our script tag is created as intended.

In Svelte to add something to the HTML head section, we just wrap it in a svelte:head tag. You can see this in lines 32 – 34. Since we have oven-ready HTML, we use the @html directive. You will see when we add a simple title meta as plaintext, later, this is not needed. The figure below shows how your finished meta will look in dev tools.

blurry low resolution placeholder image SvelteKit FAQ Page SEO: Dev Tools: Screenshot shows browser window with Dev Tools covering the bottom half.  We can see part of the HTML head section.  Shown is a snippet: &lt;script type=&quot;application/ld+json&quot;&gt; {&quot;@context&quot;:&quot;https://schema.org&quot;,&quot;@type&quot;:&quot;Question&quot;,&quot;@id&quot;:&quot;https://sveltekit-faq-page-seo.rodneylab.com/#question-3&quot;,&quot;position&quot;:3,&quot;url&quot;:&quot;https://sveltekit-faq-page-seo.rodneylab.com/#question-3&quot;,&quot;name&quot;:&quot;Does SvelteKit use vite?&quot;,&quot;answerCount&quot;:1,&quot;acceptedAnswer&quot;:{&quot;@type&quot;:&quot;Answer&quot;,&quot;text&quot;:&quot;Yes. Vite, like snowpack is a next generation bundler, building on advances earlier made by more established tools like WebPack.  Among the advantages are faster hot module reloading and better tree shaking.  These benefits come from using ES Modules.&quot;,&quot;inLanguage&quot;:&quot;en-GB&quot;},&quot;inLanguage&quot;:&quot;en-GB&quot;} &lt;/script&gt;
SvelteKit FAQ Page SEO: Dev Tools

Although we add the meta markup to the question component here, you may want to refactor so that all the SEO markup is included in a single script tag for each page. This will depend on the scale and complexity of your site. Keen to hear your philosophy on the ideal structure for different use cases.

If you want the page to look prettier, add some optional styling:

src/lib/components/Question.svelte — click to expand code.
src/lib/components/Question.svelte
svelte
    
47 <style>
48 .container {
49 display: flex;
50 background-image: linear-gradient(
51 to top left,
52 hsl(var(--colour-brand-hue) var(--colour-brand-saturation) var(--colour-brand-luminance)),
53 hsl(
54 var(--colour-brand-hue) var(--colour-brand-saturation)
55 calc(var(--colour-brand-luminance) * 0.95)
56 )
57 );
58 border-radius: var(--spacing-1);
59 margin: var(--spacing-6) auto;
60 width: 100%;
61 }
62
63 .summary {
64 padding: var(--spacing-4);
65 cursor: pointer;
66 font-weight: var(--font-weight-medium);
67 font-size: var(--mobile-font-size-2);
68 }
69
70 .question {
71 display: flex;
72 width: 100%;
73 }
74
75 .answer {
76 background-image: linear-gradient(
77 to bottom right,
78 hsl(var(--colour-mid-hue) var(--colour-mid-saturation) var(--colour-mid-luminance)),
79 hsl(
80 var(--colour-mid-hue) var(--colour-mid-saturation) calc(var(--colour-mid-luminance) * 0.8)
81 )
82 );
83 border: solid var(--spacing-px)
84 hsl(var(--colour-alt-hue) var(--colour-alt-saturation) var(--colour-alt-luminance));
85 border-radius: var(--spacing-px-2);
86 margin: var(--spacing-0) var(--spacing-4) var(--spacing-6);
87 padding: var(--spacing-0) var(--spacing-4);
88 line-height: var(--line-height-relaxed);
89 }
90
91 @media (min-width: 768px) {
92 .summary {
93 font-size: var(--font-size-2);
94 }
95 }
96 </style>

🧩 SvelteKit FAQ Page SEO: SEO Component #

src/lib/components/SEO.svelte
svelte
    
1 <script>
2 let {
3 datePublished = process.env.VITE_BUILD_TIME,
4 dateModified = process.env.VITE_BUILD_TIME,
5 seoMetaDescription,
6 url,
7 language = 'en-GB',
8 faqCount,
9 title,
10 } = $props();
11
12 const schemaOrgWebPage = {
13 '@type': ['WebPage', ...(faqCount > 0 ? ['FAQPage'] : [])],
14 '@id': `${url}#webpage`,
15 url,
16 name: title,
17 isPartOf: {
18 '@id': `${url}/#website`,
19 },
20 primaryImageOfPage: {
21 '@id': `${url}#primaryimage`,
22 },
23 ...(faqCount > 0
24 ? {
25 mainEntity: Array.from({ length: faqCount }, (_, index) => index + 1).map((element) => ({
26 '@id': `${url}#question-${element}`,
27 })),
28 }
29 : {}),
30 datePublished,
31 dateModified,
32 description: seoMetaDescription,
33 inLanguage: language,
34 potentialAction: [
35 {
36 '@type': 'ReadAction',
37 target: [url],
38 },
39 ],
40 };
41 const schemaOrgArray = [schemaOrgWebPage];
42 const schemaOrgObject = {
43 '@context': 'https://schema.org',
44 '@graph': schemaOrgArray,
45 };
46 let jsonLdString = JSON.stringify(schemaOrgObject);
47 let jsonLdScript = `
48 <script type="application/ld+json">
49 ${jsonLdString}
50 ${'<'}/script>
51 `;
52 </script>
53
54 <svelte:head>
55 <title>{title}</title>
56 <meta name="description" content={seoMetaDescription} />
57 {@html jsonLdScript}
58 </svelte:head>

It is important that you include the FAQPage type here (line 11) for Google to recognize it as an FAQ page. The code in lines 21 – 27 is also essential to this end. We won't look at rest in detail, so the post doesn't get too long. Open up the other SEO posts mentioned earlier for more details and explanation of what we have here.

That was the last component which we needed to add. Let's do some testing next.

🗳 Poll #

Have you looked at the other SEO posts on the site?
Voting reveals latest results.

💯 SvelteKit FAQ Page SEO: Testing #

Everything should be working now. You can see the JSON LD markup for your questions if you open up your browser dev tools and go to Inspector, then expand the head section. To see the data clearer, right-click on a script tag (containing application/ld+json) and select Copy / Inner HTML. This should copy just the JSON, so you can paste it into your code editor and format it to take it easy to read.

Next, deploy a test site to your favourite hosting service then crack open Google's Rich Results Test . Paste in your site's link and check Google has spotted the FAQ meta. If there are issues, Google can be quite pedantic with this particular Schema.org type, so check line by line that the meta code we added in both the Question and SEO components matches.

Please enable JavaScript to watch the video 📼

SvelteKit FAQ Page SEO: Google Rich Results Test

🙌🏽 SvelteKit FAQ Page SEO: What we Learned #

In this post we looked at:

  • why you would want to add Schema.org FAQ data to your FAQ page;
  • how simple and lightweight the Svelte code for an FAQ page can be; and
  • adding and testing Schema.org FAQ data to your SvelteKit FAQ page.

I do hope you can rip out this code and graft it into your own projects. There is a SvelteKit FAQ Page SEO Demo Page at sveltekit-faq-page-seo.rodneylab.com/ . As well as this, you can see the full completed code for this tutorial on the Rodney Lab Git Hub repo .

🏁 SvelteKit FAQ Page SEO: Summary #

Why add SEO metadata to your FAQ page #

Adding FAQ Schema.org meta to your FAQ page will get it pushed up the search rankings. Key for keeping it there is user interaction. FAQs appear larger in search results as featured snippets, and “People also ask” blocks. Including the markup helps get your page featured. Naturally, this is no substitution for good SEO, including keyword research and acing other technical SEO aspects.

How do you get your site in a Google featured snippet? #

To get your site in a Google featured snippet, the basics are more important. Your content has to be quality and engaging, covering topics Google users are interested in. On top, you should include some Schema.org meta, which we saw in this post. Using SvelteKit or Astro makes it easy to add this extra data to your page.

Is Svelte SEO friendly? #

Svelte is considered SEO friendly because it is so easy to add SEO markup to your pages. There is no need for extra dependencies; it all comes for free with built-in functionality. Naturally, considering user experience is critical for good SEO. Svelte has your back here too. Svelte makes it easy to build accessible and fast pages. On top, you can create static or server side rendered pages with SvelteKit. If you want partial hydration, Astro is a great choice.

🙏🏽 SvelteKit FAQ Page SEO: Feedback #

Have you found the post useful? Would you prefer to see posts on another topic instead? Get in touch with ideas for new posts. Also, if you like my writing style, get in touch if I can write some posts for your company site on a consultancy basis. Read on to find ways to get in touch, further below. If you want to support posts similar to this one and can spare a few dollars, euros or pounds, please consider supporting me through Buy me a Coffee.

blurry low resolution placeholder image ask Rodney X (formerly Twitter) avatar

Rodney

@askRodney

🚀 how do you get a featured snippet in Google search results?

- rich results appear larger and towards the top of search results,

- they encourage user interaction, helping your page maintain a high position on the search results page.

- Let's look at FAQ page SEO...

pic.twitter.com/qqDDsLc484

— Rodney (@askRodney) November 26, 2021

Finally, feel free to share the post on your social media accounts for all your followers who will find it useful. As well as leaving a comment below, you can get in touch via @askRodney on Twitter and also askRodney on Telegram . Also, see further ways to get in touch with Rodney Lab. I post regularly on SvelteKit as well as other topics. Also, subscribe to the newsletter to keep up-to-date with our latest projects.

Thanks for reading this post. I hope you found it valuable. Please get in touch with your feedback and suggestions for posts you would like to see. Read more about me …

blurry low resolution placeholder image Rodney from Rodney Lab
TAGS:
SVELTEKITSEO

Related Posts

blurry low resolution placeholder image Getting Started with Astro: Build React & Svelte Islands

Getting Started with Astro: Build React & Svelte Islands

astro
<PREVIOUS POST
NEXT POST >
LATEST POST >>

Leave a comment …

Your information will be handled in line with our Privacy Policy .

Comments

  • lucian

    Hello, Great post, thanks for your content. How did you solve this: ? In my case i did {#if !browser} {@html jsonldScript} {/if} but now on client side navigation json ld script is not updated, but I don't think is neede. Best regards,

    4 years ago
    • Rodney

      Hi Lucian, thanks for reaching out. If you are adding JSON-LD data manually, just make sure you include it all in the same script tag. Hope that helps
      4 years ago

Ask for more

1 Nov 2022 — Astro Server-Side Rendering: Edge Search Site
3 Oct 2022 — Svelte eCommerce Site: SvelteKit Snipcart Storefront
1 Sept 2022 — Get Started with SvelteKit Headless WordPress

Copyright © 2020 – 2025 Rodney Johnson. All Rights Reserved. Please read important copyright and intellectual property information.

  • Home
  • Profile
  • Plus +
  • Newsletter
  • Contact
  • Links
  • Terms of Use
  • Privacy Policy
We use cookies  to enhance visitors’ experience. Please click the “Options” button to make your choice.  Learn more here.