在客户端React中添加ld + json脚本标记

时间:2018-05-29 13:21:59

标签: javascript reactjs json-ld google-rich-snippets

我目前正在构建一个React应用。由于它是SPA,因此它只有一个index.html文件。我想添加2" ld + json" script标签,即某条路线的评论和书签。

我已在该组件的script中注入了componentDidMount代码,但Google结构化数据测试工具并未将其读取。

是因为Google直接从index.html读取,因为我的script标签捆绑在main.js中,所以无法读取它吗?

是否可以在客户端React执行此操作?服务器端渲染是唯一可行的方法吗?

- 详细说明--- 我目前想要实现像IMDB这样的系统,即每当我们在goole中搜索电影时; IMDB搜索结果将显示谷歌页面本身的电影评级。为此,我需要在我的index.html文件中添加一个脚本

<script type='application/ld+json'>
  {
      "@context": "http://schema.org/",
      "@type": "Review",
      "itemReviewed": {
        "@type": "Thing",
        "name": "Name"
      },
      "reviewRating": {
        "@type": "Rating",
        "ratingValue": "3",
        "bestRating": "5"
      },
      "publisher": {
        "@type": "Organization",
        "name": "1234"
      }
    }
</script>

由于我的应用是SPA,我不能把它放在我的主index.html文件中。

我目前的做法:  假设&#34; / movies / inception&#34;路线渲染&#34; MovieDetail&#34;零件。所以,我目前在这个组件的末尾添加了脚本。

import React from 'react';
import JsonLd from '../path_to_JSONLD';

class MovieDetail extends React.Component {
 render(){
 let data = {
  "@context": "http://schema.org/",
  "@type": "Review",
  "itemReviewed": {
    "@type": "Thing",
    "name": "Name"
   },
    "reviewRating": {
     "@type": "Rating",
     "ratingValue": "3",
     "bestRating": "5"
    },
   "publisher": {
     "@type": "Organization",
     "name": "1234"
    }
  }
   return(
    <SOME COMPOENTS />
    <JsonLd data={data} />

 )
}

我的JsonLd组件

import React from 'react';

const JsonLd = ({ data }) =>
  <script
    type="application/ld+json"
    dangerouslySetInnerHTML={{ __html: JSON.stringify(data) }}
  />;

  export default JsonLd;

所以,当我检查组件时;我可以看到动态添加的脚本标记。但是,在结构测试工具&#34; https://search.google.com/structured-data/testing-tool&#34; 。验证后它不会显示架构。因此,我问是否可以通过客户端完成或SSR只是解决方案,我可以提供更新的index.html作为响应。

我希望这能解决这个困惑。谢谢!

6 个答案:

答案 0 :(得分:0)

解决方案:使用&#34; react-meta-tags&#34;链接:https://github.com/s-yadav/react-meta-tags

import React from 'react';
import MetaTags from 'react-meta-tags';
import JsonLd from 'path_to_jsonld';


export default class MetaComponent extends React.Component {
  render() {
   return (
    <div className="wrapper">
      <MetaTags>
        <title>{this.props.title}</title>
        <meta property="og:type" content="website" />
        <meta name="description" content={this.props.description} />
        <meta name="og:description" content={this.props.description} />
        <meta property="og:title" content={this.props.title} />
        <meta property="og:url" content={window.location.href} />
        <meta property="og:site_name" content={"content"} 
         />
        {
          this.props.jsonLd && 
            <JsonLd data={this.props.jsonLd} />
        }
      </MetaTags>
    </div>
  )
 }
}

然后我在我的主要组件中导入了这个组件

import React from 'react';
import MetaComponent from '../path_to_Metacomponent';

class MovieDetail extends React.Component {
 render(){
let data = {
  "@context": "http://schema.org/",
  "@type": "Review",
  "itemReviewed": {
    "@type": "Thing",
    "name": "Name"
    },
"reviewRating": {
    "@type": "Rating",
    "ratingValue": "3",
    "bestRating": "5"
   },
 "publisher": {
   "@type": "Organization",
   "name": "1234"
  }
}
   return(
    <SOME COMPOENTS />
    <MetaComponent jsonLd={data} title={"abcd"} description={"xyza"} />

 )
}

软件包的作用是动态插入head标签内的脚本标签,因为现在脚本没有捆绑在main.js文件中,所以google能够从源代码中读取它。

答案 1 :(得分:0)

对我来说,React Helmet效果很好。

<Helmet>
...
<script className='structured-data-list' type="application/ld+json">{structuredJSON}</script></Helmet> 

结构化JSON类似于此类函数的结果:

export const structuredDataSingle = (prod, imgPath, availability) => {

let data = {
    "@context": "http://schema.org/",
    "@type": "Product",
    "name": `${prod.title}`,
    "image": prod.images.map((item) => imgPath + item),
    "description": prod['description'],
    "url": location.href,
    "offers": {
        "@type": "Offer",
        "priceCurrency": `${prod['currency'] || "₴"}`,
        "price": prod['price'] ? `${parseFloat(prod['price'])}` : 0,
        "availability": `${availability}`,
        "seller": {
            "@type": "Organization",
            "name": "TopMotoPro"
        }
    }
};

// brand
if(prod['brand']) {
    data['mpn'] = prod['brand'];
    data['brand'] = {
        "@type": "Thing",
        "name": `${prod['brand']}`
    };
}

// logo
if(prod['logo']){
    data['logo'] = imgPath + prod['logo'];
}

return JSON.stringify(data);

};

答案 2 :(得分:0)

根据@Дмитрий Дорогонов的建议,您可以使用React Helmet内联脚本元素。您还可以内联它们,也可以使用变量插值:

<script type="application/ld+json">{`
  {
    "@context": "http://schema.org",
    "@type": "${typeVariable}"
  }
`}</script>

答案 3 :(得分:0)

您可以简单地将其渲染为危险

<script type='application/ld+json' dangerouslySetInnerHTML={ { __html: `{ "@context": "http://schema.org", "@type": "LocalBusiness", ... }`}} />

答案 4 :(得分:0)

这对我有帮助:

  1. 准备您的 JSON 并将其字符串化。
const ORG_SCHEMA = JSON.stringify({
  "@context": "http://schema.org",
  "@type": "Organization",
  "name": "Allround",
  "description": "Allround - An online learning experience through creative and co-curricular pursuits for kids aged 5-15. Learn western vocals, keyboard, chess & Spanish from experts.",
  "url": "https://allround.club/",
  "logo": "https://allround.club/favicon.svg",
  "address": {
      "@type": "PostalAddress",
      "streetAddress": "DD3, Diamond District, HAL Old Airport Road",
      "addressLocality": "Bengaluru",
      "addressRegion": "Karnataka",
      "postalCode": "560008",
      "Telephone": "+918035003600"
  },
  "sameAs": [
      "https://www.facebook.com/Allround-Learning",
      "https://www.linkedin.com/company/allround-club",
      "https://www.instagram.com/allround.club/"
  ]
});
  1. 使用 dangerouslySetInnerHTML 在脚本标签中设置字符串化的 JSON。
<script type='application/ld+json' dangerouslySetInnerHTML={ { __html: ORG_SCHEMA} } />

您可以在此处查看它如何显示给抓取工具: https://allround.club/

答案 5 :(得分:0)

您可以使用 Google 提供的 react-schemaorg:

https://github.com/google/react-schemaorg