”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 使用 JSON-LD 提升博客的 SEO:我如何使用结构化数据添加丰富的结果

使用 JSON-LD 提升博客的 SEO:我如何使用结构化数据添加丰富的结果

发布于2024-11-07
浏览:686

Boost Your Blog’s SEO with JSON-LD: How I Added Rich Results Using Structured Data

Introduction

A few years ago in 2022, I attended SCaLE 19x. For those who are not aware, SCaLE is an acronym which stands for Southern California Linux Expo and is the name of a community-run open-source and free software conference held annually in the greater Los Angeles area.

Among the many talks given, one I attended was titledEnrich Your Enterprise Knowledge Graph with Linked Open Data via JSON-LDand presented by an individual named Jans Aasman. The talk was quite informative and broadly covered how linked open data was used and growing. Linked open data started in the semantic web community many years ago and is a tool which can be used for making web pages understandable by machines.

Subsequently, one interesting thing I learned about from the talk was how linked data could be used to enable developments in artificial intelligence since it can help make documents more understandable for machines. Given the recent advances in AI, the talk served as a good primer, sparking my interest in that area.

Unfortunately, I wasn’t aware of any practical applications for the information at the time. The talk ended with a note that Google uses JSON-LD (JavaScript Object Notation for Linked Data) for product descriptions, but that didn't resonate with me since I wasn't working on anything having to do with search at the time. Since then, I've started a blog and returned to this technology after gaining an interest in search engine optimization.

Understanding JSON-LD

What is JSON-LD? Here's a quote from Wikipedia's JSON-LD definition:

JSON-LD (JavaScript Object Notation for Linked Data) is a method of encoding linked data using JSON.

From what I understand, linked data allows the linking of data entities to each other. For example, one could define a person entity and have it linked to an article entity where the article has an author. One way to make use of JSON-LD is for SEO purposes using type definitions from https://schema.org.

As an example, here is what an ImageObject instance would look like:

{
  "@context": "https://schema.org",
  "@type": "ImageObject",
  "contentUrl": "https://logarithmicspirals.com/some-image.png"
}

From what I remember of Jans Aasman's talk at SCaLE, linked data can be used to buildknowledge graphs for both public and private use. JSON-LD is a tool to make accessing this data very simple by leveraging the simplicity and support of JSON across many programming languages. In the case of this article, JSON-LD helps contribute toGoogle's knowledge graph by providing structured data about the article.

When I first attended the talk, I wasn't working on any projects which could readily benefit from structured data or JSON-LD. However, after starting this blog I came back around to the technology after exploring the Google Search Console. Google and other search engines support certain schemas for enhancing search results. Google provides documentation about this in an article titledStructured data markup that Google Search supports.

Implementing JSON-LD for Rich Results

The first step of implementing JSON-LD for rich results was to connect the structured data markup supported by Google with the content I offer on my blog. Features like carousels for restaurant reviews aren't really something I can make use. That said, I could definitely use breadcrumb, article, and image markup.

As such, I decided to start with article markup. The article markup ended up being the most involved and least rewarding of the three. In this case, rewarding means it shows up in Google Search Console under the enhancements tab.

To start creating the JSON-LD, I looked for a TypeScript package I could install to help. Thankfully, I was able to find the package schema-dts which allows developers to create objects matching schemas from https://schema.org.

After installing the package with npm install schema-dts, I got to work on some refactoring to make it easy to add schemas to various pages.

Blog Post Article Markup

The first thing I did was create a file src/utils/get-schema.ts. In that file, I added the following code:

import type { CollectionEntry } from "astro:content";
import type { BlogPosting, WithContext, Person } from "schema-dts";

const defaultCreatorName = "Logarithmic Spirals";
const defaultCreator: Person = {
  "@type": "Person",
  "name": defaultCreatorName,
  "url": "https://logarithmicspirals.com/about/"
};

const getBlogPostingSchema = (post: CollectionEntry, url: string): WithContext => {
  const { title, description, tags, pubDate, updatedDate, heroImage } = post.data;
  const image = heroImage.src;

  return {
    "@context": "https://schema.org",
    "@type": "BlogPosting",
    "headline": title,
    "description": description,
    "keywords": tags,
    "author": defaultCreator,
    "datePublished": pubDate.toISOString(),
    ...(updatedDate && { "dateModified": updatedDate.toISOString() }),
    "image": image,
    "inLanguage": "en-US",
    "url": url
  };
};

export { getBlogPostingSchema }

The code uses the frontmatter schema I defined when I originally created the site (although it has been modified over time). Note that this code is partially influenced by code from an article titledAdding structured data to blog posts using Astro.

The getBlogPostingSchema can then be used to render the blog post pages using the blog post data.

Next, I had to update the code for my layouts to add the schema to the various pages it needs to be on. To do this, I had to update my base page layout. The base page layout is a custom layout I have defined atsrc/layouts/BasePage.astro. Here's what that looks like:

---
import type { WithContext, Thing, WebPage, WebSite, BreadcrumbList } from "schema-dts";
import BaseHead from "@components/BaseHead.astro";
import Body from "@layouts/Body.astro";

interface Props {
  title: string;
  description: string;
  image?: string;
  hasNavBar?: boolean;
  schema?: Thing;
  breadcrumb?: BreadcrumbList[] | BreadcrumbList;
}

const { title, description, image, hasNavBar, schema, breadcrumb } = Astro.props;

const webSiteSchema: WithContext = {
  "@context": "https://schema.org",
  "@type": "WebSite",
  "name": "Logarithmic Spirals",
  "url": Astro.site?.toString()
};
const webPageSchema: WithContext = {
  "@context": "https://schema.org",
  "@type": "WebPage",
  "url": new URL(Astro.url.pathname, Astro.site)   "/",
  "description": description,
  "isPartOf": webSiteSchema
};

if (breadcrumb) {
  webPageSchema.breadcrumb = breadcrumb;
}

let schemaToUse: Thing = webPageSchema;

if (schema) {
  schema["isPartOf"] = webPageSchema;
  schemaToUse = schema;
}
---



  
    

Note the separation of schema and breadcrumb. I treat those separately since not every page with a schema has a breadcrumb. The most important piece is the injection of the JSON-LD into the page through a script tag in the head of the document.

The article schema then gets passed in through child pages like this:

---
// ...
const schema: BlogPosting = getBlogPostingSchema(
  post,
  new URL(Astro.url.pathname, Astro.site).toString()   "/",
);
---

Breadcrumb Markup

For a while now, my pages have already had breadcrumb navigation elements on the individual blog post and tag pages. However, it looks like Google doesn't quite understand the HTML breadcrumb as well as it does the JSON-LD breadcrumb (note that by HTML I mean plain HTML without embedded structured data).

After adding the breadcrumb markup, I've seen links to my site have changed in Google. Where I once saw trails likehttps://logarithmicspirals.com > blog > website-migration-aws-amplify-to-cloudflare-insights, I now seehttps://logarithmicspirals.com > Blog. While a subtle difference, it shows that Google is paying attention to the newly added structured data.

To implement the breadcrumbs, I first added a new function to src/utils/get-schema.ts:

const getBlogPostBreadcrumbListSchema = (title: string, site?: URL): WithContext => {
  return {
    "@context": "https://schema.org",
    "@type": "BreadcrumbList",
    itemListElement: [
      {
        "@type": "ListItem",
        position: 1,
        name: "Home",
        item: site?.toString(),
      },
      {
        "@type": "ListItem",
        position: 2,
        name: "Blog",
        item: new URL("blog", site)   "/",
      },
      {
        "@type": "ListItem",
        position: 3,
        name: title,
      },
    ],
  };
};

The output of this function creates JSON-LD matching the examples given by Google inBreadcrumb (BreadcrumbList) structured dataand is intended to be used on pages matching this path scheme https://logarithmicspirals.com/blog/{slug}.

Image Markup

Lastly, another opportunity I saw to make use of Rich Results was on the /gallery/ page of my website. To achieve this, I created the following functions in src/utils/get-schema.ts:

const getImageObjectSchema = (imageNode: ImageNode): WithContext => {
  return {
    "@context": "https://schema.org",
    "@type": "ImageObject",
    "contentUrl": imageNode.url,
    "creator": defaultCreator,
    "creditText": defaultCreatorName,
    "copyrightNotice": defaultCreatorName
  };
};

const getImageGallerySchema = (imageNodes: Array): WithContext => {
  return {
    "@context": "https://schema.org",
    "@type": "ImageGallery",
    "image": imageNodes.map(imageNode => getImageObjectSchema(imageNode))
  };
};

The ImageNode type is a custom type I created and looks like this:

export type ImageNode = {
  key: string,
  title: string,
  technical: {
    bodyMake: string,
    bodyModel: string,
    focalLength: string,
    iso: string,
    lensMake: string,
    lensModel: string
  },
  url: string,
  nodeIndex?: number
};

For some better understanding of the ImageNode type, check out this previous article I wrote:Photo Gallery Migration: Gatsby to Astro Follow-Up.

The schema generation is then used like this:

---
// Import the IMAGES constant which is an Array of ImageNodes.
// ...
const schema = getImageGallerySchema(IMAGES);
---

Results and Google Search Console Enhancements

So far, I haven't seen a noticeable increase in traffic through Google Search, but to be fair, my blog is quite niche, and the changes haven't been live for long.

In terms of search appearance, the breadcrumbs are showing up and I've yet to check on the results for the image markup.

The most notable change has been in the Google Search Console where I'm now seeing an Enhancements section with information about the breadcrumbs and images.

Boost Your Blog’s SEO with JSON-LD: How I Added Rich Results Using Structured Data

Additionally, Google also offers the Rich Results Test which allows one to test if their markup is valid for Rich Results. This tool was quite useful while I was developing the update locally since it allows one to paste the code directly in.

Conclusion

For a small project, JSON-LD may or may not offer any benefits. In the case of my blog, it made sense to try and incorporate some into pages since it helps improve the way Google understands the content of the pages. Additionally, my blog is a tech blog, so taking the time to explore this technology offered an additional benefit of giving me something to write about. However, not every blog might benefit from incorporating it like mine.

Regardless, I think this is something other developers should consider exploring since it has a rich history and some practical applications in the web development space. For example, someone working on an eCommerce site may find rich results on Google lead to more customer engagement through organic search.

Moving forward, I want to try to find some other opportunities for improving the use of structured data on my website. One thing I would like to do is add markup for the images on blog posts. I could also explore markup for videos if I ever get around to trying my hand at making video content.

版本声明 本文转载于:https://dev.to/logarithmicspirals/boost-your-blogs-seo-with-json-ld-how-i-added-rich-results-using-structured-data-nob?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何在 PHP 中将 MySQL 结果数组转换为 JSON?
    如何在 PHP 中将 MySQL 结果数组转换为 JSON?
    将 MySQL 结果数组转换为 JSON在 PHP 中,您可以使用 json_encode() 轻松将 MySQL 结果数组转换为 JSON 格式。此函数在 PHP 版本 5.2.0 及更高版本中可用。要将 PHP 结果数组 $row 转换为 JSON,只需使用以下代码:echo json_enco...
    编程 发布于2024-11-07
  • 在 C++ 中是否有必要检查“this”是否为 Null?
    在 C++ 中是否有必要检查“this”是否为 Null?
    关于检查“this”是否为空的有用性在编程中,“this”指针指的是成员函数中的当前对象实例。它允许函数访问对象的数据和方法。然而,出现了一个问题:检查“this”是否为空是否有意义?让我们考虑一个在类中执行任务的方法:class MyClass { public: int myFuncti...
    编程 发布于2024-11-07
  • 以下是一些适合您文章的基于问题的标题:

* 如何在 PHP 中将 dd/mm/yyyy 转换为 yyyy-mm-dd:简单指南
* PHP 日期格式转换:dd/mm/yyyy 到 yyyy-mm-dd - 最佳方法
    以下是一些适合您文章的基于问题的标题: * 如何在 PHP 中将 dd/mm/yyyy 转换为 yyyy-mm-dd:简单指南 * PHP 日期格式转换:dd/mm/yyyy 到 yyyy-mm-dd - 最佳方法
    PHP 日期格式转换:dd/mm/yyyy 到 yyyy-mm-dd在 dd/mm/yyyy 和 之间转换日期格式yyyy-mm-dd 在 PHP 中可能具有挑战性。问题:使用 dd/mm/yyyy 格式的日期时会出现主要问题。由于斜杠分隔符 (/) 造成歧义,PHP 通常采用美国 m/d/y 格式...
    编程 发布于2024-11-07
  • 为什么Go函数中修改指针有时不影响原值?
    为什么Go函数中修改指针有时不影响原值?
    Go中指针的修改,理解差异在Go中,当将指针传递给函数时,我们通常会修改值该指针所指向的。通常,这可以通过取消引用来实现,如以下代码所示:type Test struct { Value int } func main() { i := Test{2} p := &i...
    编程 发布于2024-11-07
  • 周构建互动游戏
    周构建互动游戏
    第 2 周:构建互动游戏 第三课:游戏物理与运动 3.1 理解游戏物理 游戏物理涉及模拟现实世界的物理,使游戏更加真实和引人入胜。速度、加速度和重力等基本物理原理可以使游戏中的动作和交互感觉自然。 3.1.1 速度和加速度 速度是物体...
    编程 发布于2024-11-07
  • 如何使用 BeautifulSoup 从 Python 中的 HTML 表中提取数据?
    如何使用 BeautifulSoup 从 Python 中的 HTML 表中提取数据?
    BeautifulSoup解析表在Python中,BeautifulSoup提供了强大的解析HTML文档的方法。当遇到这样的场景,您需要从表中检索特定数据时,BeautifulSoup 就派上用场了。要提取目标行项目表,请使用 soup.find(),在表中指定适当的属性括号。在这种情况下,您需要:...
    编程 发布于2024-11-07
  • 如何在react中使用PKCE实现oAuth以进行第三方集成
    如何在react中使用PKCE实现oAuth以进行第三方集成
    在为第三方集成实现oAuth时,我偶然发现了一些很长一段时间没有更新的信息。在这里,我试图记录我的经验及其运作方式 注意:本文不会详细讨论oAuth及其工作原理。主要关注如何在 React 应用程序中配置和实现它们。如果您想了解 oAuth,请阅读此处。提供清晰的信息。 流程: 大...
    编程 发布于2024-11-07
  • 为什么我在 POST Jersey 请求中收到不支持的媒体类型错误?
    为什么我在 POST Jersey 请求中收到不支持的媒体类型错误?
    POST Jersey 请求中不支持的媒体类型错误遇到 HTTP 状态代码 415 - 对 Jersey 的 POST 请求中不支持的媒体类型REST 服务,问题通常在于 Jersey 发行版中缺少 JSON/POJO 支持。要解决此错误,需要在项目中添加必要的 JAR 依赖项。具体来说,需要以下依...
    编程 发布于2024-11-07
  • 针对 XSS 的常见防御措施有哪些?
    针对 XSS 的常见防御措施有哪些?
    针对 XSS 的常见防御输入和输出清理是防止跨站脚本 (XSS) 攻击的关键技术。本文探讨了行业和个人网站广泛采用的减轻这种威胁的方法。1。 HTML 转义:在将所有用户输入显示为 HTML 代码之前彻底转义它们。这涉及将“”、“&”和“等字符替换为其相应的 HTML 实体(例如,“”、“&”、“”...
    编程 发布于2024-11-07
  • Python垃圾收集器如何自动管理内存?
    Python垃圾收集器如何自动管理内存?
    Python 垃圾收集器文档Python 垃圾收集器是一个内存管理系统,可以自动释放程序不再使用的内存。这有助于通过防止内存泄漏并确保程序不会耗尽内存来提高性能。垃圾收集器的工作过程分为两步:引用计数: 解释器跟踪每个对象的引用数量。当引用计数达到零时,该对象被认为不可达,并被添加到要删除的对象列表...
    编程 发布于2024-11-07
  • PHP 如何高效处理大整数?
    PHP 如何高效处理大整数?
    PHP 可以处理大整数吗?PHP 可能没有显式的“BigInteger”类,但它提供了几种处理大整数的方法使用 BC 数学函数PHP 提供 BC 数学函数,如 bcadd() 和 bcsub() 进行整数运算。然而,这种方法对于大量计算来说可能会很慢。使用 GMP 扩展GMP(GNU 多精度算术)是...
    编程 发布于2024-11-07
  • 如何使用 Python 字符串匹配验证 IP 地址输入?
    如何使用 Python 字符串匹配验证 IP 地址输入?
    使用 Python 验证 IP 地址输入验证用户输入的 IP 地址在各种应用中至关重要。本文将探讨验证以字符串形式提供的 IP 地址合法性的最有效方法。首选方法偏离解析,而是利用 Python 标准库的套接字模块。通过利用 inet_aton(),我们可以确定输入字符串是否代表有效的 IP 地址:i...
    编程 发布于2024-11-07
  • 那么 Pull 请求如何再次发挥作用呢?屏显#3
    那么 Pull 请求如何再次发挥作用呢?屏显#3
    在我之前的文章中,我谈到了启动一个基于开源 GenAI 的终端应用程序。本周的任务是为另一个用户的项目贡献一个新功能。由于我们必须与新人合作,所以我与 Lily 合作,她开发了一款应用程序,其代码改进功能与我的类似,只是她的角色是老鼠! 有时间的话可以去看看她的项目老鼠助手。 她的代码是用 Type...
    编程 发布于2024-11-07
  • 为什么 Go 中不能直接将 []string 转换为 []interface{}?
    为什么 Go 中不能直接将 []string 转换为 []interface{}?
    为什么将 []string 转换为 []interface{} 会在 Go 中引发编译错误转换字符串切片 ([]string)考虑到它们共享切片特征以及 []string 的每个元素都可以被视为一个接口,Go 中的接口切片 ([]interface{}) 似乎很简单。然而,尝试这种转换时会出现编译错...
    编程 发布于2024-11-07
  • 理解 Shadow DOM:封装 Web 组件的关键
    理解 Shadow DOM:封装 Web 组件的关键
    在现代 Web 开发中,创建可重用和可维护的组件至关重要。 Shadow DOM 是 Web 组件标准的一部分,在实现这一目标方面发挥着至关重要的作用。本文深入探讨了 Shadow DOM 的概念、它的优点以及如何在您的项目中有效地使用它。 什么是 Shadow DOM? Shado...
    编程 发布于2024-11-07

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3