How to add Google Structured Data in a Frontity way?

Hello Frontity team,

I’ve noticed that Google offers a better optimization for recipe related websites with including the Google Structured Data approach. See more about here: https://developers.google.com/search/docs/data-types/recipe. So, want to implement this on https://ruthgeorgiev.com.

The way Google needs this data is pretty much straightforward, simply by creating a <script> element with the type set to application/ld+json in the <head> of the page. And then inside the <script> element, have to tell Google i’ll be using schema.org structured data by setting @context to http://schema.org .
Also need to tell Google what kind of thing i’m describing, by adding @type to Recipe .

<html>
<head>
<script type="application/ld+json">
{
  "@context": "http://schema.org/",
  "@type": "Recipe"
}
</script>
</head>
</html>

And at the end i have to add all of the required and precommended properties into the json.

Example:

<html>
<head>
...
<script type="application/ld+json">
  {
  "@context": "http://schema.org/",
  "@type": "Recipe",
  "name": "Party Coffee Cake",
  "image": "https://www.leannebrown.com/wp-content/uploads/2016/12/up-close-pear-cake.jpg",
  "author": {
    "@type": "Person",
    "name": "Mary Stone"
  },
  "datePublished": "2018-03-10",
  "description": "This coffee cake is awesome and perfect for parties.",
    "prepTime": "PT20M",
    "cookTime": "PT30M",
    "totalTime": "PT50M",
    "recipeYield": "10 servings",
    "recipeCategory": "Dessert",
    "recipeCuisine": "American",
    "keywords": "cake for a party, coffee",
    "nutrition": {
      "@type": "NutritionInformation",
      "calories": "270 calories"
     },
      "recipeIngredient": [
        "2 cups of flour",
        "3/4 cup white sugar",
        "2 teaspoons baking powder",
        "1/2 teaspoon salt",
        "1/2 cup butter",
        "2 eggs",
        "3/4 cup milk"
       ],
    "recipeInstructions": [
      {
      "@type": "HowToStep",
      "text": "Preheat the oven to 350 degrees F. Grease and flour a 9x9 inch pan."
      },
      {
      "@type": "HowToStep",
      "text": "In a medium bowl, combine flour, sugar, and cinnamon."
      },
      {
      "@type": "HowToStep",
      "text": "Mix in butter until the entire mixture is crumbly."
      },
      {
      "@type": "HowToStep",
      "text": "In a large bowl, combine flour, sugar, baking powder, and salt."
      },
      {
      "@type": "HowToStep",
      "text": "Mix in the butter."
      },
      {
      "@type": "HowToStep",
      "text": "Spread into the prepared pan."
      },
      {
      "@type": "HowToStep",
      "text": "Sprinkle the streusel mixture on top of the cake."
      },
      {
      "@type": "HowToStep",
      "text": "Bake for 30 to 35 minutes, or until firm."
      },
      {
      "@type": "HowToStep",
      "text": "Allow to cool."
     }
  ],
  "video": [
     {
    "@type": "VideoObject", 
    "name": "How to make a Party Coffee Cake",
    "description": "This is how you make a Party Coffee Cake.",
    "thumbnailUrl": [
      "https://example.com/photos/1x1/photo.jpg",
      "https://example.com/photos/4x3/photo.jpg",
      "https://example.com/photos/16x9/photo.jpg"
     ],
    "contentUrl": "http://www.example.com/video123.flv",
    "embedUrl": "http://www.example.com/videoplayer.swf?video=123",
    "uploadDate": "2018-02-05T08:00:00+08:00",
    "duration": "PT1M33S",
    "interactionStatistic": {
      "@type": "InteractionCounter",
      "interactionType": { "@type": "http://schema.org/WatchAction" },
      "userInteractionCount": 2347
     },
    "expires": "2019-02-05T08:00:00+08:00"
   }
  ]
}
</script>
</head>
</html>

Full description here: https://codelabs.developers.google.com/codelabs/structured-data/index.html#2

Now, i already have all of this data ready in post.js, so my question here is, is there any elegant Frontity way of how to push this data in a required format into <head> tag?

<html>
<head>
<script type="application/ld+json">
{
/* Recipe Data */
}
</script>
</head>
</html>

Any recommendation will be greatly appreciated. :nerd_face:

Many thanks.
All the best,
Dejan

Hi @dejangeorgiev,

frontity package provides the Head component that you can use to add any meta-tag to the header

You should be able to add any metadata from any component. In this case as you need to use a custom JSON , you need to add this JSON as a string, using backticks, so you can use variables inside the string

import { Head } from "frontity";

const Post = ({ state }) =>  {

  const data = state.source.get(state.router.link);
  const recipe = state.source.recipe[data.id];
  const recipeTitle = recipe.title

  return (
    <Head>
      <script type="application/ld+json">
        {
           `
          {
             "@context": "http://schema.org/",
             "@type": "Recipe",
             "name": ${recipeTitle}
           }
           `
        }
      </script>
    </Head>
    )
  }
;

Another solution that may work for you is adding (somehow, maybe with the help of some WordPress plugin) this script tag information (in JSON format) from WordPress so Frontity can directly add this info through its html2react package

We haven’t really tested any of these two approaches so come back to us with any problem you may find by implementing them

Hope this helps

1 Like

Hey @juanma :wave:t3:

Thanks so much for your feedback.

Well actually there are some plugins like Yoast

and WP Recipe Maker

But i think the best approach will be to use either Google Tag manager or Custom JS as it is recommended by Google itself here: https://developers.google.com/search/docs/guides/generate-structured-data-with-javascript

Yes, this can be achieved with plugins, it will be much easier if i use the same domain for the frontend, but since i use Frontity and have different domain for the backend this is a bit overhelming.

Btw, in Yoast i can’t find the Recipe type (in case you want to implement this in the @frontity/yoast package.

I think i will go for your proposal, by adding a custom JS. By this i will have more control over the data i send in the future.

One more question, if i do this like you described in your comment

import { Head } from "frontity";

const Post = ({ state }) =>  {

  const data = state.source.get(state.router.link);
  const recipe = state.source.recipe[data.id];
  const recipeTitle = recipe.title

  return (
    <Head>
      <script type="application/ld+json">
        {
           `
          {
             "@context": "http://schema.org/",
             "@type": "Recipe",
             "name": ${recipeTitle}
           }
           `
        }
      </script>
    </Head>
    )
  }
;

Does that mean that in <Head></Head> will be included only the additional <script type="application/ld+json"></script> tag? Or will <Head> be completely overwritten?

Thank you very much for your help! :slight_smile:

You can add tags to the final <head> from different components by using the <Head> react component available in frontity. They will all be added to the <head> of the final HTML even if they have been added from different component

You can check this in twenty-twenty-theme

As you can see in the code, the <Head> component is being used from different components adding different meta-tags

If you check the source code of https://twentytwenty.frontity.org/

You can see how this meta-data is added to the final HTML generated by Frontity

1 Like

Hi @juanma :wave:t3:

All clear, great to know i can do that. Thank you very much! :slight_smile:

1 Like