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

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

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

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]删除
最新教程 更多>
  • 如何使用node-mysql在单个查询中执行多个SQL语句?
    如何使用node-mysql在单个查询中执行多个SQL语句?
    Multi-Statement Query Support in Node-MySQLIn Node.js, the question arises when executing multiple SQL statements in a single query using the node-mys...
    编程 发布于2025-05-12
  • 如何使用Java.net.urlConnection和Multipart/form-data编码使用其他参数上传文件?
    如何使用Java.net.urlConnection和Multipart/form-data编码使用其他参数上传文件?
    使用http request 上传文件上传到http server,同时也提交其他参数,java.net.net.urlconnection and Multipart/form-data Encoding是普遍的。 Here's a breakdown of the process:Mu...
    编程 发布于2025-05-12
  • 如何从PHP中的Unicode字符串中有效地产生对URL友好的sl。
    如何从PHP中的Unicode字符串中有效地产生对URL友好的sl。
    为有效的slug生成首先,该函数用指定的分隔符替换所有非字母或数字字符。此步骤可确保slug遵守URL惯例。随后,它采用ICONV函数将文本简化为us-ascii兼容格式,从而允许更广泛的字符集合兼容性。接下来,该函数使用正则表达式删除了不需要的字符,例如特殊字符和空格。此步骤可确保slug仅包含...
    编程 发布于2025-05-12
  • 如何在无序集合中为元组实现通用哈希功能?
    如何在无序集合中为元组实现通用哈希功能?
    在未订购的集合中的元素要纠正此问题,一种方法是手动为特定元组类型定义哈希函数,例如: template template template 。 struct std :: hash { size_t operator()(std :: tuple const&tuple)const {...
    编程 发布于2025-05-12
  • 我可以将加密从McRypt迁移到OpenSSL,并使用OpenSSL迁移MCRYPT加密数据?
    我可以将加密从McRypt迁移到OpenSSL,并使用OpenSSL迁移MCRYPT加密数据?
    将我的加密库从mcrypt升级到openssl 问题:是否可以将我的加密库从McRypt升级到OpenSSL?如果是这样,如何?答案:是的,可以将您的Encryption库从McRypt升级到OpenSSL。可以使用openssl。附加说明: [openssl_decrypt()函数要求iv参...
    编程 发布于2025-05-12
  • 图片在Chrome中为何仍有边框?`border: none;`无效解决方案
    图片在Chrome中为何仍有边框?`border: none;`无效解决方案
    在chrome 中删除一个频繁的问题时,在与Chrome and IE9中的图像一起工作时,遇到了一个频繁的问题。和“边境:无;”在CSS中。要解决此问题,请考虑以下方法: Chrome具有忽略“ border:none; none;”的已知错误,风格。要解决此问题,请使用以下CSS ID块创建带...
    编程 发布于2025-05-12
  • 如何实时捕获和流媒体以进行聊天机器人命令执行?
    如何实时捕获和流媒体以进行聊天机器人命令执行?
    在开发能够执行命令的chatbots的领域中,实时从命令执行实时捕获Stdout,一个常见的需求是能够检索和显示标准输出(stdout)在cath cath cant cant cant cant cant cant cant cant interfaces in Chate cant inter...
    编程 发布于2025-05-12
  • 如何使用FormData()处理多个文件上传?
    如何使用FormData()处理多个文件上传?
    )处理多个文件输入时,通常需要处理多个文件上传时,通常是必要的。 The fd.append("fileToUpload[]", files[x]); method can be used for this purpose, allowing you to send multi...
    编程 发布于2025-05-12
  • 如何正确使用与PDO参数的查询一样?
    如何正确使用与PDO参数的查询一样?
    在pdo 中使用类似QUERIES在PDO中的Queries时,您可能会遇到类似疑问中描述的问题:此查询也可能不会返回结果,即使$ var1和$ var2包含有效的搜索词。错误在于不正确包含%符号。通过将变量包含在$ params数组中的%符号中,您确保将%字符正确替换到查询中。没有此修改,PDO...
    编程 发布于2025-05-12
  • 如何处理PHP文件系统功能中的UTF-8文件名?
    如何处理PHP文件系统功能中的UTF-8文件名?
    在PHP的Filesystem functions中处理UTF-8 FileNames 在使用PHP的MKDIR函数中含有UTF-8字符的文件很多flusf-8字符时,您可能会在Windows Explorer中遇到comploreer grounder grounder grounder gro...
    编程 发布于2025-05-12
  • 在细胞编辑后,如何维护自定义的JTable细胞渲染?
    在细胞编辑后,如何维护自定义的JTable细胞渲染?
    在JTable中维护jtable单元格渲染后,在JTable中,在JTable中实现自定义单元格渲染和编辑功能可以增强用户体验。但是,至关重要的是要确保即使在编辑操作后也保留所需的格式。在设置用于格式化“价格”列的“价格”列,用户遇到的数字格式丢失的“价格”列的“价格”之后,问题在设置自定义单元格...
    编程 发布于2025-05-12
  • Python高效去除文本中HTML标签方法
    Python高效去除文本中HTML标签方法
    在Python中剥离HTML标签,以获取原始的文本表示Achieving Text-Only Extraction with Python's MLStripperTo streamline the stripping process, the Python standard librar...
    编程 发布于2025-05-12
  • Python环境变量的访问与管理方法
    Python环境变量的访问与管理方法
    Accessing Environment Variables in PythonTo access environment variables in Python, utilize the os.environ object, which represents a mapping of envir...
    编程 发布于2025-05-12
  • 如何使用Depimal.parse()中的指数表示法中的数字?
    如何使用Depimal.parse()中的指数表示法中的数字?
    在尝试使用Decimal.parse(“ 1.2345e-02”中的指数符号表示法表示的字符串时,您可能会遇到错误。这是因为默认解析方法无法识别指数符号。 成功解析这样的字符串,您需要明确指定它代表浮点数。您可以使用numbersTyles.Float样式进行此操作,如下所示:[&& && && ...
    编程 发布于2025-05-12
  • 您如何在Laravel Blade模板中定义变量?
    您如何在Laravel Blade模板中定义变量?
    在Laravel Blade模板中使用Elegance 在blade模板中如何分配变量对于存储以后使用的数据至关重要。在使用“ {{}}”分配变量的同时,它可能并不总是最优雅的解决方案。幸运的是,Blade通过@php Directive提供了更优雅的方法: $ old_section =“...
    编程 发布于2025-05-12

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

Copyright© 2022 湘ICP备2022001581号-3