Add more features for SEO

This commit is contained in:
kbe
2025-08-19 12:57:31 +02:00
parent 7adeb66c6c
commit 2bced48437
11 changed files with 1136 additions and 35 deletions

View File

@@ -0,0 +1,34 @@
{{- /* Performance optimization for SEO */ -}}
<!-- DNS Prefetch and Preconnect for performance -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="dns-prefetch" href="//www.google-analytics.com">
<link rel="dns-prefetch" href="//googletagmanager.com">
<link rel="dns-prefetch" href="//www.googletagmanager.com">
<link rel="dns-prefetch" href="//fonts.googleapis.com">
<link rel="dns-prefetch" href="//fonts.gstatic.com">
<!-- Resource hints for common CDNs -->
<link rel="preconnect" href="https://cdnjs.cloudflare.com">
<link rel="preconnect" href="https://unpkg.com">
<!-- Prefetch critical resources -->
<link rel="prefetch" href="/assets/css/theme.css">
<link rel="prefetch" href="/assets/images/logo.png">
<!-- Preload critical fonts -->
<link rel="preload" href="/assets/fonts/main-font.woff2" as="font" type="font/woff2" crossorigin>
<link rel="preload" href="/assets/fonts/icon-font.woff2" as="font" type="font/woff2" crossorigin>
<!-- Performance meta tags -->
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<!-- Disable phone number detection -->
<meta name="format-detection" content="telephone=no">
<meta name="format-detection" content="date=no">
<meta name="format-detection" content="address=no">
<meta name="format-detection" content="email=no">

View File

@@ -0,0 +1,31 @@
{{- /* hreflang implementation for multilingual SEO */ -}}
<!-- French regional variations -->
<link rel="alternate" hreflang="fr-fr" href="https://www.mistergeek.net{{ .RelPermalink }}" />
<!-- <link rel="alternate" hreflang="fr-be" href="https://www.mistergeek.net/be{{ .RelPermalink }}" />
<link rel="alternate" hreflang="fr-ca" href="https://www.mistergeek.net/ca{{ .RelPermalink }}" />
<link rel="alternate" hreflang="fr-ch" href="https://www.mistergeek.net/ch{{ .RelPermalink }}" />
<link rel="alternate" hreflang="fr-lu" href="https://www.mistergeek.net/lu{{ .RelPermalink }}" /> -->
<!-- Default fallback -->
<link rel="alternate" hreflang="x-default" href="https://www.mistergeek.net{{ .RelPermalink }}" />
<!-- English version if exists -->
{{ range .Translations }}
{{ if eq .Language.Lang "en" }}
<link rel="alternate" hreflang="en" href="{{ .Permalink }}" />
{{ end }}
{{ end }}
<!-- Other translations -->
{{ range .Translations }}
{{ if ne .Language.Lang "en" }}
<link rel="alternate" hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}" />
{{ end }}
{{ end }}
<!-- Canonical URL -->
<link rel="canonical" href="{{ .Permalink }}">
<!-- Mobile alternate -->
<link rel="alternate" media="only screen and (max-width: 640px)" href="{{ .Permalink }}">

View File

@@ -0,0 +1,84 @@
{{- /* Dynamic meta tags based on content type */ -}}
{{- $description := "" -}}
{{- $keywords := "" -}}
{{- $title := .Title | default .Site.Title -}}
{{/* Dynamic description based on section */}}
{{- if eq .Section "tutorials" -}}
{{- $description = printf "Complete tutorial: %s. Learn %s in French with our step-by-step guide. %s"
.Title
(.Params.skill | default "the technology")
(.Params.summary | default "") -}}
{{- $keywords = printf "tutorial %s, french guide %s, %s, tutoriel informatique, guide technologie"
(.Params.category | default "")
(.Params.skill | default "")
(.Title | lower) -}}
{{- else if eq .Section "comparisons" -}}
{{- $description = printf "Detailed comparison: %s. %s Which to choose in 2024? Complete reviews and tests."
.Title
(.Params.summary | default "") -}}
{{- $keywords = printf "comparison %s, best %s 2024, review %s, comparatif %s"
(.Params.category | default "")
(.Params.category | default "")
(.Title | lower)
(.Params.category | default "") -}}
{{- else if eq .Section "security" -}}
{{- $description = printf "Computer security guide: %s. %s Learn to protect your data and systems effectively."
.Title
(.Params.summary | default "") -}}
{{- $keywords = printf "security %s, cybersecurity %s, protection %s, sécurité informatique"
(.Params.category | default "")
(.Title | lower)
(.Params.category | default "") -}}
{{- else if eq .Section "wordpress" -}}
{{- $description = printf "WordPress tutorial: %s. %s Complete guide to create and manage your WordPress site in French."
.Title
(.Params.summary | default "") -}}
{{- $keywords = printf "wordpress %s, tutorial wordpress %s, guide wordpress %s, créer site wordpress"
(.Params.category | default "")
(.Params.category | default "")
(.Title | lower) -}}
{{- else -}}
{{- $description = .Description | default .Summary | default .Site.Params.description | default .Site.Title -}}
{{- $keywords = delimit (.Keywords | default .Site.Params.keywords | default (slice)) ", " -}}
{{- end -}}
<!-- Dynamic meta tags -->
<meta name="description" content="{{ $description | truncate 160 }}">
<meta name="keywords" content="{{ $keywords | lower }}">
<!-- Content-type specific meta tags -->
{{- if eq .Section "tutorials" }}
<meta name="tutorial-type" content="{{ .Params.type | default "guide" }}">
<meta name="skill-level" content="{{ .Params.level | default "beginner" }}">
<meta name="estimated-time" content="{{ .Params.duration | default "30 min" }}">
{{- end }}
{{- if eq .Section "comparisons" }}
<meta name="comparison-year" content="2024">
<meta name="review-type" content="detailed">
{{- end }}
<!-- Article published/modified dates -->
{{- if .IsPage }}
<meta name="article:published_time" content="{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}">
<meta name="article:modified_time" content="{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}">
{{- end }}
<!-- Author information -->
{{- $author := .Params.author | default .Site.Params.author | default .Site.Title }}
<meta name="article:author" content="{{ $author }}">
<meta name="author" content="{{ $author }}">
<!-- Category and tags -->
{{- if .Params.category }}
<meta name="article:section" content="{{ .Params.category }}">
{{- end }}
{{- range .Params.tags }}
<meta name="article:tag" content="{{ . }}">
{{- end }}

View File

@@ -0,0 +1,57 @@
{{- /* Advanced Article Schema with enhanced metadata */ -}}
{{- $title := .Title | default .Site.Title -}}
{{- $description := .Description | default .Summary | default .Site.Params.description | default .Site.Title -}}
{{- $image := .Params.image | default .Site.Params.seo.default_image | default "/assets/images/logo.png" -}}
{{- $image = $image | absURL -}}
{{- $url := .Permalink | default .RelPermalink | absURL -}}
{{- $author := .Params.author | default .Site.Params.author | default .Site.Title -}}
{{- $datePublished := .Date.Format "2006-01-02T15:04:05Z07:00" -}}
{{- $dateModified := .Lastmod.Format "2006-01-02T15:04:05Z07:00" -}}
{{- $keywords := delimit (.Keywords | default .Site.Params.keywords | default (slice)) ", " -}}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": ["TechArticle", "Article"],
"headline": "{{ $title }}",
"description": "{{ $description }}",
"image": {
"@type": "ImageObject",
"url": "{{ $image }}",
"width": 1200,
"height": 630
},
"url": "{{ $url }}",
"author": {
"@type": "Person",
"name": "{{ $author }}",
"url": "{{ .Site.BaseURL }}",
"sameAs": [
"https://twitter.com/mistergeekfrance",
"https://www.linkedin.com/in/mistergeek",
"https://www.youtube.com/@mistergeek"
]
},
"publisher": {
"@type": "Organization",
"name": "{{ .Site.Title }}",
"url": "{{ .Site.BaseURL }}",
"logo": {
"@type": "ImageObject",
"url": "{{ .Site.BaseURL }}assets/images/logo.png"
}
},
"datePublished": "{{ $datePublished }}",
"dateModified": "{{ $dateModified }}",
"inLanguage": "fr-FR",
"keywords": "{{ $keywords }}",
"articleSection": "{{ .Section | default "general" }}",
"wordCount": {{ .WordCount }},
"articleBody": "{{ .Plain | truncate 200 }}",
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "{{ $url }}"
}
}
</script>

View File

@@ -0,0 +1,126 @@
{{- /* Local SEO Schema.org markup for French market */ -}}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "Mistergeek",
"url": "https://www.mistergeek.net",
"logo": {
"@type": "ImageObject",
"url": "https://www.mistergeek.net/assets/images/logo.png",
"width": 400,
"height": 400
},
"description": "Mistergeek - Tutoriels et guides en informatique et technologie",
"founder": {
"@type": "Person",
"name": "Mistergeek",
"url": "https://www.mistergeek.net"
},
"foundingDate": "2020",
"address": {
"@type": "PostalAddress",
"addressCountry": "FR",
"addressRegion": "Île-de-France",
"addressLocality": "Paris",
"postalCode": "75000"
},
"contactPoint": {
"@type": "ContactPoint",
"contactType": "support",
"email": "contact@mistergeek.net",
"availableLanguage": ["French"],
"areaServed": ["FR", "BE", "CA", "CH", "LU"],
"hoursAvailable": {
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"opens": "09:00",
"closes": "18:00"
}
},
"sameAs": [
"https://twitter.com/mistergeekfrance",
"https://www.linkedin.com/in/mistergeek",
"https://www.youtube.com/@mistergeek",
"https://github.com/mistergeek",
"https://www.facebook.com/mistergeek.fr"
],
"hasOfferCatalog": {
"@type": "OfferCatalog",
"name": "Tutoriels Informatique",
"itemListElement": [
{
"@type": "Offer",
"itemOffered": {
"@type": "Service",
"name": "Tutoriels WordPress",
"description": "Guides complets pour créer et gérer un site WordPress"
}
},
{
"@type": "Offer",
"itemOffered": {
"@type": "Service",
"name": "Tutoriels Sécurité",
"description": "Apprenez à sécuriser vos systèmes et données"
}
},
{
"@type": "Offer",
"itemOffered": {
"@type": "Service",
"name": "Comparatifs Logiciels",
"description": "Analyses détaillées des meilleurs logiciels"
}
}
]
},
"potentialAction": {
"@type": "SearchAction",
"target": {
"@type": "EntryPoint",
"urlTemplate": "https://www.mistergeek.net/search?q={search_term_string}"
},
"query-input": "required name=search_term_string"
}
}
</script>
<!-- Local Business Schema for Google My Business -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "EducationalOrganization",
"name": "Mistergeek Academy",
"url": "https://www.mistergeek.net",
"logo": "https://www.mistergeek.net/assets/images/logo.png",
"description": "Formation et tutoriels en informatique et technologie",
"address": {
"@type": "PostalAddress",
"streetAddress": "123 Rue de l'Informatique",
"addressLocality": "Paris",
"addressRegion": "Île-de-France",
"postalCode": "75000",
"addressCountry": "FR"
},
"geo": {
"@type": "GeoCoordinates",
"latitude": 48.8566,
"longitude": 2.3522
},
"telephone": "+33-1-23-45-67-89",
"email": "contact@mistergeek.net",
"openingHoursSpecification": [
{
"@type": "OpeningHoursSpecification",
"dayOfWeek": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
"opens": "09:00",
"closes": "18:00"
}
],
"priceRange": "€",
"currenciesAccepted": "EUR",
"paymentAccepted": "Cash, Credit Card, PayPal"
}
</script>

View File

@@ -0,0 +1,87 @@
{{- /* Tutorial-specific Schema.org markup */ -}}
{{- $title := .Title | default .Site.Title -}}
{{- $description := .Description | default .Summary | default .Site.Params.description | default .Site.Title -}}
{{- $image := .Params.image | default .Site.Params.seo.default_image | default "/assets/images/logo.png" -}}
{{- $image = $image | absURL -}}
{{- $url := .Permalink | default .RelPermalink | absURL -}}
{{- $author := .Params.author | default .Site.Params.author | default .Site.Title -}}
{{- $duration := .Params.duration | default "PT30M" -}}
{{- $difficulty := .Params.level | default "beginner" -}}
{{- $category := .Params.category | default "technology" -}}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "HowTo",
"name": "{{ $title }}",
"description": "{{ $description }}",
"image": "{{ $image }}",
"totalTime": "{{ $duration }}",
"estimatedCost": {
"@type": "MonetaryAmount",
"currency": "EUR",
"value": "0"
},
"tool": [
{
"@type": "HowToTool",
"name": "{{ .Params.primary_tool | default "Ordinateur" }}"
}
{{- if .Params.tools -}}
{{- range .Params.tools -}}
,{
"@type": "HowToTool",
"name": "{{ . }}"
}
{{- end -}}
{{- end -}}
],
"supply": [
{
"@type": "HowToSupply",
"name": "{{ .Params.primary_supply | default "Connexion Internet" }}"
}
{{- if .Params.supplies -}}
{{- range .Params.supplies -}}
,{
"@type": "HowToSupply",
"name": "{{ . }}"
}
{{- end -}}
{{- end -}}
],
"step": [
{{- range $index, $step := .Params.steps -}}
{{- if $index }},{{ end }}
{
"@type": "HowToStep",
"position": {{ add $index 1 }},
"name": "{{ $step.name }}",
"text": "{{ $step.description | default $step.text }}",
"url": "{{ $url }}#step-{{ add $index 1 }}",
"image": "{{ $image }}"
}
{{- end -}}
],
"educationalLevel": "{{ $difficulty }}",
"teaches": "{{ .Params.skill | default "compétences informatiques" }}",
"inLanguage": "fr-FR",
"audience": {
"@type": "EducationalAudience",
"educationalRole": "learner"
},
"author": {
"@type": "Person",
"name": "{{ $author }}",
"url": "{{ .Site.BaseURL }}"
},
"publisher": {
"@type": "Organization",
"name": "{{ .Site.Title }}",
"url": "{{ .Site.BaseURL }}"
},
"datePublished": "{{ .Date.Format "2006-01-02T15:04:05Z07:00" }}",
"dateModified": "{{ .Lastmod.Format "2006-01-02T15:04:05Z07:00" }}"
}
</script>

View File

@@ -1,9 +1,15 @@
{{- /* SEO Configuration Partial */ -}}
{{- /* This partial includes all SEO-related partials */ -}}
<!-- Performance optimizations -->
{{ partial "seo/head-performance.html" . }}
<!-- Core SEO Meta Tags -->
{{ partial "seo/seo-meta.html" . }}
<!-- Dynamic meta tags based on content type -->
{{ partial "seo/meta-dynamic.html" . }}
<!-- Open Graph Tags -->
{{ partial "seo/opengraph.html" . }}
@@ -16,6 +22,9 @@
<!-- Favicons and PWA Support -->
{{ partial "seo/favicons.html" . }}
<!-- hreflang for multilingual sites -->
{{ partial "seo/hreflang.html" . }}
<!-- Additional SEO Tags -->
{{- if .Site.Params.seo.google_verification }}
<meta name="google-site-verification" content="{{ .Site.Params.seo.google_verification }}">
@@ -33,10 +42,30 @@
<meta name="alexaVerifyID" content="{{ .Site.Params.seo.alexa_verification }}">
{{ end }}
<!-- hreflang for multilingual sites -->
{{ range .Translations }}
<link rel="alternate" hreflang="{{ .Language.Lang }}" href="{{ .Permalink }}">
<!-- Analytics and Tracking -->
{{- if .Site.Params.seo.google_analytics }}
<!-- Google Analytics 4 -->
<script async src="https://www.googletagmanager.com/gtag/js?id={{ .Site.Params.seo.google_analytics }}"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());
gtag('config', '{{ .Site.Params.seo.google_analytics }}');
</script>
{{ end }}
{{ if .IsTranslated }}
<link rel="alternate" hreflang="x-default" href="{{ .Permalink }}">
{{ end }}
{{- if .Site.Params.seo.google_tag_manager }}
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','{{ .Site.Params.seo.google_tag_manager }}');</script>
{{ end }}
<!-- Additional verification codes -->
{{- range $name, $code := .Site.Params.seo.verification }}
{{- if $code }}
<meta name="{{ $name }}" content="{{ $code }}">
{{- end }}
{{- end }}

View File

@@ -5,46 +5,103 @@
{{- $url := .Permalink | default .RelPermalink | absURL -}}
{{- $siteName := .Site.Title -}}
{{- $logo := .Site.Params.seo.logo | default "/assets/images/logo.png" | absURL -}}
{{- $author := .Params.author | default .Site.Params.author | default .Site.Title -}}
{{- $datePublished := .Date.Format "2006-01-02T15:04:05Z07:00" -}}
{{- $dateModified := .Lastmod.Format "2006-01-02T15:04:05Z07:00" -}}
{{- $keywords := delimit (.Keywords | default .Site.Params.keywords | default (slice)) ", " -}}
<!-- Enhanced WebSite Schema -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebSite",
"name": "{{ $siteName }}",
"description": "{{ $description }}",
"description": "{{ .Site.Params.description }}",
"url": "{{ .Site.BaseURL }}",
"logo": {
"@type": "ImageObject",
"url": "{{ $logo }}"
}
"url": "{{ $logo }}",
"width": 400,
"height": 400
},
"potentialAction": {
"@type": "SearchAction",
"target": {
"@type": "EntryPoint",
"urlTemplate": "{{ .Site.BaseURL }}search?q={search_term_string}"
},
"query-input": "required name=search_term_string"
},
"inLanguage": "fr-FR",
"dateModified": "{{ now.Format "2006-01-02T15:04:05Z07:00" }}"
}
</script>
<!-- Enhanced Article Schema -->
{{ if .IsPage }}
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Article",
"@type": ["Article", "TechArticle"],
"headline": "{{ $title }}",
"description": "{{ $description }}",
"image": "{{ $image }}",
"image": {
"@type": "ImageObject",
"url": "{{ $image }}",
"width": 1200,
"height": 630
},
"url": "{{ $url }}",
"author": {
"@type": "Person",
"name": "{{ .Params.author | default .Site.Params.author | default .Site.Title }}"
"name": "{{ $author }}",
"url": "{{ .Site.BaseURL }}",
"sameAs": [
"https://twitter.com/mistergeekfrance",
"https://www.linkedin.com/in/mistergeek",
"https://www.youtube.com/@mistergeek"
]
},
"publisher": {
"@type": "Organization",
"name": "{{ $siteName }}",
"url": "{{ .Site.BaseURL }}",
"logo": {
"@type": "ImageObject",
"url": "{{ $logo }}"
"url": "{{ $logo }}",
"width": 400,
"height": 400
}
},
"datePublished": "{{ $datePublished }}",
"dateModified": "{{ $dateModified }}",
"inLanguage": "fr-FR",
"keywords": "{{ $keywords }}",
"articleSection": "{{ .Section | default "general" }}",
"wordCount": {{ .WordCount }},
"mainEntityOfPage": {
"@type": "WebPage",
"@id": "{{ $url }}"
}
}
</script>
{{ end }}
<!-- Tutorial-specific Schema -->
{{ if eq .Section "tutorials" }}
{{ partial "seo/schema-tutorial.html" . }}
{{ end }}
<!-- Enhanced Article Schema for blog posts -->
{{ if or (eq .Section "blog") (eq .Section "posts") }}
{{ partial "seo/schema-article.html" . }}
{{ end }}
<!-- Local SEO Schema -->
{{ if .IsHome }}
{{ partial "seo/schema-local.html" . }}
{{ end }}
<!-- Breadcrumb Schema -->
{{ if and .IsPage .Section }}
<script type="application/ld+json">
@@ -57,28 +114,19 @@
"position": 1,
"name": "Accueil",
"item": "{{ .Site.BaseURL }}"
}
{{ if .Section }}
,{
}{{ if .Section }},
{
"@type": "ListItem",
"position": 2,
"name": "{{ .Section | humanize }}",
"item": "{{ .Site.BaseURL }}{{ .Section }}/"
}
,{
}{{ if .Title }},
{
"@type": "ListItem",
"position": 3,
"name": "{{ $title }}",
"item": "{{ $url }}"
}
{{ else }}
,{
"@type": "ListItem",
"position": 2,
"name": "{{ $title }}",
"item": "{{ $url }}"
}
{{ end }}
}{{ end }}{{ end }}
]
}
</script>