Merge pull request #2 from cojocaru-david/feat/added-posthead-tracking-and-improved-seo
feat: enhance PostHead component with SEO improvements and add Postho…
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 2.0 MiB After Width: | Height: | Size: 2.6 MiB |
@@ -10,38 +10,55 @@ const { post } = Astro.props
|
|||||||
|
|
||||||
const title = post.data.title || SITE.title
|
const title = post.data.title || SITE.title
|
||||||
const description = post.data.description || SITE.description
|
const description = post.data.description || SITE.description
|
||||||
const image = new URL('/image/' + post.id + '.png', Astro.site).toString()
|
const postUrl = new URL(post.id, SITE.href).toString()
|
||||||
|
const image = SITE.href + '/image/' + post.id + '.png';
|
||||||
const author = post.data.authors ? post.data.authors.join(', ') : SITE.author
|
const author = post.data.authors ? post.data.authors.join(', ') : SITE.author
|
||||||
|
|
||||||
|
const wordsPerMinute = 200;
|
||||||
|
const wordCount = post.body ? post.body.split(/\s+/).length : 0;
|
||||||
|
const readTime = Math.max(1, Math.round(wordCount / wordsPerMinute));
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<!-- Basic Meta Tags -->
|
||||||
<title>{`${title} - ${SITE.title}`}</title>
|
<title>{`${title} - ${SITE.title}`}</title>
|
||||||
<meta name="title" content={`${title} | ${SITE.title}`} />
|
<meta name="title" content={`${title} | ${SITE.title}`} />
|
||||||
<meta name="description" content={description} />
|
<meta name="description" content={description} />
|
||||||
<link rel="canonical" href={SITE.href} />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<meta name="robots" content="index, follow" />
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||||
|
<meta name="author" content={author} />
|
||||||
|
{post?.data.tags && <meta name="keywords" content={post.data.tags.join(', ')} />}
|
||||||
|
|
||||||
|
<!-- Canonical URL -->
|
||||||
|
<link rel="canonical" href={postUrl} />
|
||||||
|
|
||||||
|
<!-- Open Graph / Facebook -->
|
||||||
<meta property="og:title" content={title} />
|
<meta property="og:title" content={title} />
|
||||||
<meta property="og:description" content={description} />
|
<meta property="og:description" content={description} />
|
||||||
<meta
|
<meta property="og:image" content={image} />
|
||||||
property="og:image"
|
|
||||||
content={`${SITE.href}${post?.data?.image?.src}` || image}
|
|
||||||
/>
|
|
||||||
<meta property="og:image:alt" content={title} />
|
<meta property="og:image:alt" content={title} />
|
||||||
<meta property="og:type" content="website" />
|
<meta property="og:type" content="article" />
|
||||||
<meta property="og:locale" content={SITE.locale} />
|
<meta property="og:locale" content={SITE.locale} />
|
||||||
<meta property="og:site_name" content={SITE.title} />
|
<meta property="og:site_name" content={SITE.title} />
|
||||||
<meta property="og:url" content={Astro.url} />
|
<meta property="og:url" content={postUrl} />
|
||||||
<meta property="og:author" content={author} />
|
<meta property="og:author" content={author} />
|
||||||
|
<meta property="article:published_time" content={post.data.date.toISOString()} />
|
||||||
|
<meta property="article:modified_time" content={post.data.date.toISOString()} />
|
||||||
|
<meta property="article:section" content={post.data.tags ? post.data.tags.join(', ') : ''} />
|
||||||
|
<meta property="article:published" content={post.data.date.toISOString()} />
|
||||||
|
<meta property="article:author" content={author} />
|
||||||
|
<meta property="article:publisher" content={SITE.title} />
|
||||||
|
<meta property="article:tag" content={post?.data.tags ? post.data.tags.join(', ') : ''} />
|
||||||
|
|
||||||
|
<!-- Twitter -->
|
||||||
<meta name="twitter:title" content={title} />
|
<meta name="twitter:title" content={title} />
|
||||||
<meta name="twitter:description" content={description} />
|
<meta name="twitter:description" content={description} />
|
||||||
<meta
|
<meta property="twitter:image" content={image} />
|
||||||
property="twitter:image"
|
|
||||||
content={`${SITE.href}${post?.data?.image?.src}` || image}
|
|
||||||
/>
|
|
||||||
<meta name="twitter:image:alt" content={title} />
|
<meta name="twitter:image:alt" content={title} />
|
||||||
<meta name="twitter:card" content="summary_large_image" />
|
<meta name="twitter:card" content="summary_large_image" />
|
||||||
<meta name="twitter:creator" content={author} />
|
<meta name="twitter:creator" content={author} />
|
||||||
|
|
||||||
|
<!-- Individual Tags -->
|
||||||
{
|
{
|
||||||
post?.data.tags &&
|
post?.data.tags &&
|
||||||
post.data.tags.map((tag: string) => {
|
post.data.tags.map((tag: string) => {
|
||||||
@@ -49,11 +66,32 @@ const author = post.data.authors ? post.data.authors.join(', ') : SITE.author
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
<meta
|
<!-- JSON-LD Structured Data -->
|
||||||
property="article:published_time"
|
<script type="application/ld+json" set:html={JSON.stringify({
|
||||||
content={post.data.date.toISOString()}
|
"@context": "https://schema.org",
|
||||||
/>
|
"@type": "BlogPosting",
|
||||||
<meta property="article:modified_time" content={post.data.date.toISOString()} />
|
"headline": title,
|
||||||
<meta property="article:author" content={author} />
|
"description": description,
|
||||||
<meta property="article:published" content={post.data.date.toISOString()} />
|
"image": image,
|
||||||
<meta property="article:modified" content={post.data.date.toISOString()} />
|
"author": {
|
||||||
|
"@type": "Person",
|
||||||
|
"name": author
|
||||||
|
},
|
||||||
|
"publisher": {
|
||||||
|
"@type": "Organization",
|
||||||
|
"name": SITE.title,
|
||||||
|
"logo": {
|
||||||
|
"@type": "ImageObject",
|
||||||
|
"url": new URL("/favicon.ico", SITE.href).toString()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"datePublished": post.data.date.toISOString(),
|
||||||
|
"dateModified": post.data.date.toISOString(),
|
||||||
|
"mainEntityOfPage": {
|
||||||
|
"@type": "WebPage",
|
||||||
|
"@id": postUrl
|
||||||
|
},
|
||||||
|
"keywords": post?.data.tags ? post.data.tags.join(', ') : '',
|
||||||
|
"url": postUrl,
|
||||||
|
"readingTime": `${readTime} min read`
|
||||||
|
})} />
|
||||||
59
src/components/Posthog.astro
Normal file
59
src/components/Posthog.astro
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
---
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<script is:inline>
|
||||||
|
!(function (t, e) {
|
||||||
|
var o, n, p, r;
|
||||||
|
e.__SV ||
|
||||||
|
((window.posthog = e),
|
||||||
|
(e._i = []),
|
||||||
|
(e.init = function (i, s, a) {
|
||||||
|
function g(t, e) {
|
||||||
|
var o = e.split(".");
|
||||||
|
2 == o.length && ((t = t[o[0]]), (e = o[1])),
|
||||||
|
(t[e] = function () {
|
||||||
|
t.push([e].concat(Array.prototype.slice.call(arguments, 0)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
((p = t.createElement("script")).type = "text/javascript"),
|
||||||
|
(p.crossOrigin = "anonymous"),
|
||||||
|
(p.async = !0),
|
||||||
|
(p.src =
|
||||||
|
s.api_host.replace(".i.posthog.com", "-assets.i.posthog.com") +
|
||||||
|
"/static/array.js"),
|
||||||
|
(r = t.getElementsByTagName("script")[0]).parentNode.insertBefore(
|
||||||
|
p,
|
||||||
|
r
|
||||||
|
);
|
||||||
|
var u = e;
|
||||||
|
for (
|
||||||
|
void 0 !== a ? (u = e[a] = []) : (a = "posthog"),
|
||||||
|
u.people = u.people || [],
|
||||||
|
u.toString = function (t) {
|
||||||
|
var e = "posthog";
|
||||||
|
return (
|
||||||
|
"posthog" !== a && (e += "." + a), t || (e += " (stub)"), e
|
||||||
|
);
|
||||||
|
},
|
||||||
|
u.people.toString = function () {
|
||||||
|
return u.toString(1) + ".people (stub)";
|
||||||
|
},
|
||||||
|
o =
|
||||||
|
"init capture register register_once register_for_session unregister unregister_for_session getFeatureFlag getFeatureFlagPayload isFeatureEnabled reloadFeatureFlags updateEarlyAccessFeatureEnrollment getEarlyAccessFeatures on onFeatureFlags onSessionId getSurveys getActiveMatchingSurveys renderSurvey canRenderSurvey identify setPersonProperties group resetGroups setPersonPropertiesForFlags resetPersonPropertiesForFlags setGroupPropertiesForFlags resetGroupPropertiesForFlags reset get_distinct_id getGroups get_session_id get_session_replay_url alias set_config startSessionRecording stopSessionRecording sessionRecordingStarted captureException loadToolbar get_property getSessionProperty createPersonProfile opt_in_capturing opt_out_capturing has_opted_in_capturing has_opted_out_capturing clear_opt_in_out_capturing debug getPageViewId captureTraceFeedback captureTraceMetric".split(
|
||||||
|
" "
|
||||||
|
),
|
||||||
|
n = 0;
|
||||||
|
n < o.length;
|
||||||
|
n++
|
||||||
|
)
|
||||||
|
g(u, o[n]);
|
||||||
|
e._i.push([i, s, a]);
|
||||||
|
}),
|
||||||
|
(e.__SV = 1));
|
||||||
|
})(document, window.posthog || []);
|
||||||
|
posthog.init("phc_orIpAm9v5xuxdhe4wd5FhkyTJ7ygykslwxxeCESZquz", {
|
||||||
|
api_host: "https://eu.i.posthog.com",
|
||||||
|
person_profiles: "identified_only",
|
||||||
|
});
|
||||||
|
</script>
|
||||||
@@ -7,6 +7,7 @@ import Head from '@/components/Head.astro'
|
|||||||
import Navbar from '@/components/react/navbar'
|
import Navbar from '@/components/react/navbar'
|
||||||
import { SITE } from '@/consts'
|
import { SITE } from '@/consts'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
|
import Posthog from '@/components/Posthog.astro'
|
||||||
|
|
||||||
const { isWide = false } = Astro.props
|
const { isWide = false } = Astro.props
|
||||||
---
|
---
|
||||||
@@ -23,6 +24,7 @@ const { isWide = false } = Astro.props
|
|||||||
<link rel="preload" href="/fonts/GeistVF.woff2" as="font" crossorigin="anonymous" />
|
<link rel="preload" href="/fonts/GeistVF.woff2" as="font" crossorigin="anonymous" />
|
||||||
<link rel="preload" href="/fonts/_montserrat_bold.ttf" as="font" crossorigin="anonymous" />
|
<link rel="preload" href="/fonts/_montserrat_bold.ttf" as="font" crossorigin="anonymous" />
|
||||||
<link rel="preload" href="/fonts/_montserrat_regular.ttf" as="font" crossorigin="anonymous" />
|
<link rel="preload" href="/fonts/_montserrat_regular.ttf" as="font" crossorigin="anonymous" />
|
||||||
|
<link rel="sitemap" href="/sitemap-index.xml" />
|
||||||
<script is:inline data-astro-rerun>
|
<script is:inline data-astro-rerun>
|
||||||
(function() {
|
(function() {
|
||||||
try {
|
try {
|
||||||
@@ -45,6 +47,7 @@ const { isWide = false } = Astro.props
|
|||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
<Posthog />
|
||||||
</Head>
|
</Head>
|
||||||
<body>
|
<body>
|
||||||
<div class="flex h-fit min-h-screen w-full flex-col gap-y-4 sm:gap-y-6 font-sans">
|
<div class="flex h-fit min-h-screen w-full flex-col gap-y-4 sm:gap-y-6 font-sans">
|
||||||
@@ -61,5 +64,15 @@ const { isWide = false } = Astro.props
|
|||||||
</main>
|
</main>
|
||||||
<Footer />
|
<Footer />
|
||||||
</div>
|
</div>
|
||||||
|
<script async src="https://www.googletagmanager.com/gtag/js?id=G-QVK59XQK72"
|
||||||
|
></script>
|
||||||
|
<script is:inline>
|
||||||
|
window.dataLayer = window.dataLayer || [];
|
||||||
|
function gtag() {
|
||||||
|
dataLayer.push(arguments);
|
||||||
|
}
|
||||||
|
gtag("js", new Date());
|
||||||
|
gtag("config", "G-QVK59XQK72");
|
||||||
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ export async function GET(context: APIContext) {
|
|||||||
<div style="position: absolute;display: flex; width: 100%; height: 100%; background-color: rgba(255, 255, 255, 0.01); opacity: 0.6;"></div>
|
<div style="position: absolute;display: flex; width: 100%; height: 100%; background-color: rgba(255, 255, 255, 0.01); opacity: 0.6;"></div>
|
||||||
|
|
||||||
|
|
||||||
<div style="position: absolute; width: 350px; height: 350px;display: flex; background: radial-gradient(circle, rgba(100, 100, 255, 0.12) 0%, transparent 70%); top: -100px; right: -50px; border-radius: 50%;"></div>
|
<div style="position: absolute; width: 350px; height: 350px;display: flex; background: radial-gradient(circle, rgba(250, 255, 100, 0.12) 0%, transparent 70%); top: -100px; right: -50px; border-radius: 50%;"></div>
|
||||||
|
|
||||||
|
|
||||||
<div style="flex: 4; padding: 48px 50px; display: flex; flex-direction: column; justify-content: center; position: relative;">
|
<div style="flex: 4; padding: 48px 50px; display: flex; flex-direction: column; justify-content: center; position: relative;">
|
||||||
|
|||||||
Reference in New Issue
Block a user