- Full Time Instructor @VueSchool
- Masterclass Lead Instructor
- Full Stack developer
ostafa
&
uxt
ue
ESSENTIALS
S
E
O
What is
S
E
O
?
What is
S
E
O
?
What is
S
E
O
?
What is
S
E
O
?
What is
S
E
O
?
HAPPY
S
earch
E
ngines
=
HIGH TRAFFIC
How do
S
earch
E
ngines
visit a website?
S
earch
E
ngine
Crawlers
S
earch
E
ngine
Crawlers
S
earch
E
ngine
Crawlers
S
earch
E
ngine
Crawlers
🌐
Server
Request
fetch('https://vueschool.io/')
S
earch
E
ngine
Crawlers
🌐
Server
Request
Response
<!DOCTYPE html>
<html>
<head> .. </head>
<body> .. </body>
</html>
HTML
fetch('https://vueschool.io/')
S
earch
E
ngine
Crawlers
🌐
Server
Request
Response
<!DOCTYPE html>
<html>
<head> .. </head>
<body> .. </body>
</html>
HTML
🔎
The returned HTML contains the actual content when rendered server side
<!DOCTYPE html>
<html>
<head> .. </head>
<body>
<main> Actual content .. </main>
</body>
</html>
HTML
🔎
fetch('https://vueschool.io/')
S
earch
E
ngine
Crawlers
🌐
Server
Request
Response
<!DOCTYPE html>
<html>
<head> .. </head>
<body> .. </body>
</html>
HTML
🔎
Or, referencing the needed JavaScript files to render the content in the browser
<!DOCTYPE html>
<html>
<head> .. </head>
<body>
<div id='app'></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
HTML
🔎
fetch('https://vueschool.io/')
S
earch
E
ngine
Crawlers
🌐
Server
Request
Response
<!DOCTYPE html>
<html>
<head> .. </head>
<body> .. </body>
</html>
HTML
🔎
Or, referencing the needed JavaScript files to render the content in the browser
<!DOCTYPE html>
<html>
<head> .. </head>
<body>
<div id='app'></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
HTML
🔎
Watch out!
fetch('https://vueschool.io/')
S
earch
E
ngine
Crawlers
🌐
Server
Request
Response
<!DOCTYPE html>
<html>
<head> .. </head>
<body> .. </body>
</html>
HTML
🔎
<!DOCTYPE html>
<html>
<head> .. </head>
<body>
<div id='app'></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
Watch out!
fetch('https://vueschool.io/')
✅ Yes! SEO is possible for client-side apps.
S
earch
E
ngine
Crawlers
🌐
Server
Request
Response
<!DOCTYPE html>
<html>
<head> .. </head>
<body> .. </body>
</html>
HTML
🔎
<!DOCTYPE html>
<html>
<head> .. </head>
<body>
<div id='app'></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
Watch out!
fetch('https://vueschool.io/')
⛔️ No! It's not as quick or efficient as SSR.
S
earch
E
ngine
Crawlers
🌐
Server
Request
Response
<!DOCTYPE html>
<html>
<head> .. </head>
<body> .. </body>
</html>
HTML
Visually Rendered Page
https://vueschoo.io
fetch('https://vueschool.io/')
S
earch
E
ngine
Crawlers
🌐
Server
Request
Response
<!DOCTYPE html>
<html>
<head> .. </head>
<body> .. </body>
</html>
HTML
fetch('https://vueschool.io/')
https://vueschoo.io
Visually Rendered Page
Scan and Index the Content
S
earch
E
ngine
Crawlers
Our goal
S
earch
E
ngine
Crawlers
Our goal
are able to
crawl your site by default
Crawlers
3 main things to ensure
Crawlers
can explore your site
Page is publicly accessible
No blocking meta tags, headers or Robots.txt
3 main things to ensure
Crawlers
can explore your site
<meta name="robots" content="noindex">
HTTP/1.1 200 OK
(...)
X-Robots-Tag: noindex
(...)
User-agent: *
Disallow: /
3 main things to ensure
Crawlers
can explore your site
Page is publicly accessible
No blocking meta tags, headers or Robots.txt
Indexable file type
3 main things to ensure
Crawlers
can explore your site
Page is publicly accessible
No blocking meta tags, headers or Robots.txt
Not Spammy
But we can do more..
We can help search engines discover our pages
Optimize Links
Optimize Links
Optimize Links
Optimize Links
Fully visible
Hidden with CSS
<NuxtLink :to="{ name: 'posts', params: { id: 1 } }">
Post 123
</NuxtLink>
<RouterLink :to="{ name: 'posts', params: { id: 1 } }">
Post 123
</RouterLink>
Optimize Links
Sitemaps
Sitemaps
export default defineNuxtConfig({
sitemap: {
sources: [
'/api/__sitemap__/urls',
]
}
})
npx nuxi@latest module add sitemap
Sitemaps
We can provide more details about our content
Meta Tags
Meta Tags
Meta Tags
Meta Tags
<script setup>
import { useMeta } from 'vue-meta'
useMeta({
title: 'Vue School',
htmlAttrs: {
lang: 'en',
}
})
</script>
npm install vue-meta@next --save
Meta Tags
Meta Tags
Canonicalization
Canonicalization
vueschool.io/courses?sortBy=Desc
vueschool.io/courses
Canonicalization
<head>
<link rel="canonical" href="https://vueschool.com/courses">
</head>
http or https?
www or without?
Trailing slash?
Query strings?
vueschool.io/courses?sortBy=Desc
vueschool.io/courses
Structured Data Markup
Structured Data Markup
Structured Data Markup
Structured Data Markup
<script type="application/ld+json">
{
"@context": "https://schema.org/",
"@type": "Recipe",
"name": "Party Coffee Cake",
"author": {
"@type": "Person",
"name": "Mary Stone"
},
"datePublished": "2018-03-10",
"description": "This coffee cake is awesome and perfect for parties.",
"prepTime": "PT20M"
}
</script>
Structured Data Markup
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['nuxt-jsonld'],
});
npm install nuxt-jsonld
Your page experience matters
Your page experience matters
HTTP/HTTPS?
Mobile friendly?
Interfering Ads?
Valuable content?
Core Web Vitals
Core Web Vitals
Test Page Performance: https://pagespeed.web.dev/
How fast does it take the browser to show the final, stable visual version of the main content in the page?
Core Web Vitals
Search engines loves speed
Core Web Vitals
Reduce JS Bundle Size
<script setup lang="ts">
import { ref, defineAsyncComponent } from 'vue'
const show = ref(false)
const BigListComponent = defineAsyncComponent(() => {
import('@/components/BigListComponent.vue')
})
</script>
<template>
<BigListComponent v-if="show" />
</template>
Reduce JS Bundle Size
<script setup lang="ts">
import { ref, defineAsyncComponent } from 'vue'
const show = ref(false)
const BigListComponent = defineAsyncComponent(() => {
import('@/components/BigListComponent.vue')
})
</script>
<template>
<BigListComponent v-if="show" />
</template>
Reduce JS Bundle Size
<script setup lang="ts">
const show = ref(false)
</script>
<template>
<LazyHeavyComponent v-if="show" />
</template>
Reduce JS Bundle Size
<script setup lang="ts">
const show = ref(false)
</script>
<template>
<LazyHeavyComponent v-if="show" />
</template>
Reduce JS Bundle Size
Reduce Unused CSS
Reduce Unused CSS
Reduce Unused CSS
Reduce Unused CSS
Optimize Images
<NuxtImg
src="/images/hero.png"
alt="Vue School landing ..."
sizes="400px md:1280px"
width="1280"
height="720"
provider="ipx"
/>
Optimize Images
<img
src="/_ipx/s_2560x1440/images/hero.png"
alt="Vue School Logo"
width="1280"
height="720"
sizes="(max-width: 768px) 400px, 1280px"
srcset="
/_ipx/s_400x225/images/hero.png 400w,
/_ipx/s_800x450/images/hero.png 800w,
/_ipx/s_1280x720/images/hero.png 1280w,
/_ipx/s_2560x1440/images/hero.png 2560w
"
/>
=
HTML
<NuxtImg
src="/images/hero.png"
alt="Vue School landing ..."
sizes="400px md:1280px"
width="1280"
height="720"
provider="ipx"
format="webp"
/>
// or AVIF
Optimize Images
<NuxtImg
src="/images/hero.png"
alt="Vue School landing ..."
sizes="400px md:1280px"
width="1280"
height="720"
provider="ipx"
format="webp"
loading="lazy"
placeholder
/>
Optimize Images
<NuxtImg
src="/images/hero.png"
alt="Vue School landing ..."
sizes="400px md:1280px"
width="1280"
height="720"
provider="ipx"
format="webp"
loading="eager"
preload
/>
Optimize Images
So much more we can do!
Vue.js Masterclass 2024 Edition
@Moose_Said
I'll tweet (or "X" ?) out the slides after this