Repository: garmeeh/next-seo
Pull request #1188 (2023-03-20 10:11:57)

Add cateogry property to product json-ld prop type
## Description of Change(s):
- Add `category` property to `ProductJsonLdProps` type – ensuring the Product props are defined according to https://schema.org/Product 

---

To help get PR's merged faster, the following is required:

--> As it's a single optional prop type, no additional tests are necessary.

[ ] Updated the documentation
[ ] Unit/Cypress test covering all cases

Please link to relevant Google Docs or schema.org docs for what you are adding so we can review.

- https://schema.org/Product 

Please have a read of the Contributing Guide for full details.

https://github.com/garmeeh/next-seo/blob/master/CONTRIBUTING.md



Patch:
diff --git a/APP_DIRECTORY.md b/APP_DIRECTORY.md
index 34c98b4..d3d6127 100644
--- a/APP_DIRECTORY.md
+++ b/APP_DIRECTORY.md
@@ -1,451 +1,1 @@
-# Next.js App Directory Support
-
-> ⚠ Warning: Currently, the Head export does not re-render on client-side transitions, only on initial render. Read more [here](https://beta.nextjs.org/docs/api-reference/file-conventions/head#:~:text=Warning%3A%20Currently%2C%20the%20Head%20export%20does%20not%20re%2Drender%20on%20client%2Dside%20transitions%2C%20only%20on%20initial%20render.
-)
-
-With the introduction of the app directory there have been a lot of changes to how the `<head>` is now handled internally by Next.js.
-As a result of this, how we use `NextSeo` in our apps will also change.
-
-Please remember that the app directory is in beta and active development by the Next.js team. This means that the recommended way to use
-`NextSeo` below may be subject to change as the core logic of Next.js changes.
-
-### Research
-
-If you are interested I carried out some testing and gave feedback to the Next.js team that you can read. They give insight into how I landed on the new suggested use for `NextSeo`
-
-- [Feedback on head.js](https://github.com/vercel/next.js/discussions/41745#discussioncomment-4011958)
-- [Feedback on JSON-LD/inline script tags](https://github.com/vercel/next.js/discussions/41745#discussioncomment-4012381)
-
-### Key Changes
-
-- Next.js no longer de-duplicates tags in the head. This means that we can no longer use `<DefaultSeo />` in the same way. Going forward we will solely use `<NextSeo />`
-- `head.js` does not currently support `<script>` tags that do no have `src=""`. So for JSON-LD components they now have to be added via the page. This will result in them being added to the `<body>` of the page. This is 100% ok for SEO and not to worry about. This was confirmed by Google. I have also validated this using schema tool.
-- Next.js no longer auto adds the tags below to your app that you will likely need. I suggest adding them to your root layout in a `<head>` tag.
-
-```html
-<head>
-  <meta charset="utf-8" />
-  <meta name="viewport" content="width=device-width" />
-</head>
-```
-
-### Recommended Usage
-
-#### 1. Set your absolute defaults
-
-As I mentioned there is no de-duplication so anything we add as a default will appear on every page and can not be changed. I recommend identifying what your absolute defaults are and
-setting them in your root layout. `/app/layout.js`
-
-An example might be root layout might look something like this:
-
-```jsx
-// app/layout.js
-import { NextSeo } from 'next-seo';
-
-export default function RootLayout({ children }) {
-  return (
-    <html>
-      <head>
-        {/* Used to be added by default, now we need to add manually */}
-        <meta charSet="utf-8" />
-        <meta name="viewport" content="width=device-width" />
-        {/* 
-          Anything we add in layout will appear on EVERY PAGE. At present it can not be overridden lower down the tree.
-          This can be useful for things like favicons, or other meta tags that are the same on every page.
-        */}
-        <NextSeo
-          useAppDir={true}
-          facebook={{ appId: '1234567890' }}
-          themeColor="#73fa97"
-          titleTemplate="%s | Next SEO"
-        />
-      </head>
-      <body>{children}</body>
-    </html>
-  );
-}
-```
-
-#### 2. Do you want default meta?
-
-Maybe you like having some fallback og:images, titles, descriptions etc. If so we can still achieve this with the caveat of you will still need to import `<NextSeo />` on every `page/head.js` that you want meta tags.
-
-If you would like default meta then I suggest creating a `next-seo.config.js` file.
-
-Example:
-
-```js
-// next-seo.config.js
-export const NEXT_SEO_DEFAULT = {
-  title: 'Title A',
-  description: 'Description A',
-  openGraph: {
-    type: 'website',
-    locale: 'en_IE',
-    url: 'https://www.url.ie/a',
-    title: 'Open Graph Title A',
-    description: 'Open Graph Description A',
-    images: [
-      {
-        url: 'https://www.test.ie/og-image-a-01.jpg',
-        width: 800,
-        height: 600,
-        alt: 'Og Image Alt A',
-        type: 'image/jpeg',
-        secureUrl: 'https://www.test.ie/secure-og-image-a-01.jpg',
-      },
-    ],
-    siteName: 'SiteName A',
-  },
-  twitter: {
-    handle: '@handlea',
-    site: '@sitea',
-    cardType: 'summary_large_image',
-  },
-};
-```
-
-or Typescript:
-
-```ts
-// next-seo.config.ts
-import type { NextSeoProps } from 'next-seo';
-
-export const NEXT_SEO_DEFAULT: NextSeoProps = {
-  title: 'Title A',
-  description: 'Description A',
-  openGraph: {
-    type: 'website',
-    locale: 'en_IE',
-    url: 'https://www.url.ie/a',
-    title: 'Open Graph Title A',
-    description: 'Open Graph Description A',
-    images: [
-      {
-        url: 'https://www.test.ie/og-image-a-01.jpg',
-        width: 800,
-        height: 600,
-        alt: 'Og Image Alt A',
-        type: 'image/jpeg',
-        secureUrl: 'https://www.test.ie/secure-og-image-a-01.jpg',
-      },
-    ],
-    siteName: 'SiteName A',
-  },
-  twitter: {
-    handle: '@handlea',
-    site: '@sitea',
-    cardType: 'summary_large_image',
-  },
-};
-```
-
-Now in any page you want to add meta data you can do the following.
-
-Remember we now need to use the `head.js` file that sits alongside the `page.js` file.
-
-```js
-// app/head.js
-import { NextSeo } from 'next-seo';
-
-import { NEXT_SEO_DEFAULT } from './next-seo.config'; // your path will vary
-
-export default async function Head() {
-  return <NextSeo {...NEXT_SEO_DEFAULT} useAppDir={true} />;
-}
-```
-
-**IMPORTANT**: Notice the new prop `useAppDir`. This is important as it makes `NextSeo` use the app directory compatible version.
-
-If you would like to see output after following step 1. & 2. expand below.
-
-<details>
-<summary>Output of the above steps</summary>
-
-```html
-<head>
-  <!-- These come from your layout -->
-  <meta charset="utf-8" />
-  <meta name="viewport" content="width=device-width" />
-  <meta name="robots" content="index,follow" />
-  <meta name="theme-color" content="#73fa97" />
-  <meta property="fb:app_id" content="1234567890" />
-
-  <!-- These come from your head.js in step 2 -->
-  <title>Title A | Next SEO</title>
-  <meta name="description" content="Description A" />
-  <meta name="twitter:card" content="summary_large_image" />
-  <meta name="twitter:site" content="@sitea" />
-  <meta name="twitter:creator" content="@handlea" />
-  <meta property="og:title" content="Open Graph Title A" />
-  <meta property="og:description" content="Open Graph Description A" />
-  <meta property="og:url" content="https://www.url.ie/a" />
-  <meta property="og:type" content="website" />
-  <meta property="og:image" content="https://www.test.ie/og-image-a-01.jpg" />
-  <meta property="og:image:alt" content="Og Image Alt A" />
-  <meta
-    property="og:image:secure_url"
-    content="https://www.test.ie/secure-og-image-a-01.jpg"
-  />
-  <meta property="og:image:type" content="image/jpeg" />
-  <meta property="og:image:width" content="800" />
-  <meta property="og:image:height" content="600" />
-  <meta property="og:locale" content="en_IE" />
-  <meta property="og:site_name" content="SiteName A" />
-</head>
-```
-
-</details>
-
-#### 3. Re-use your default meta
-
-Now that you have your default meta defined in a config, you can reuse it on other pages. For example if you have a new page you can override
-where needed. Here is an example of `head.js` in another page.
-
-```jsx
-// app/example/head.js
-import { NextSeo } from 'next-seo';
-
-import { NEXT_SEO_DEFAULT } from '../../next-seo.config'; // your path may vary
-
-export default async function Head() {
-  const updateMeta: NextSeoProps = {
-    ...NEXT_SEO_DEFAULT,
-    title: 'Example Page',
-    description: 'This is an example page',
-    titleTemplate: '%s',
-  };
-  return <NextSeo {...updateMeta} useAppDir={true} />;
-}
-```
-
-Here you are setting a new title, description and removing the title template for this page.
-
-<details>
-<summary>Output of this:</summary>
-
-```html
-<head>
-  <!-- These come from your layout -->
-  <meta charset="utf-8" />
-  <meta name="viewport" content="width=device-width" />
-  <meta name="robots" content="index,follow" />
-  <meta name="theme-color" content="#73fa97" />
-  <meta property="fb:app_id" content="1234567890" />
-
-  <!-- These come from your head.js above -->
-  <title>Example Page</title>
-  <meta name="description" content="This is an example page" />
-  <meta name="twitter:card" content="summary_large_image" />
-  <meta name="twitter:site" content="@sitea" />
-  <meta name="twitter:creator" content="@handlea" />
-  <meta property="og:title" content="Open Graph Title A" />
-  <meta property="og:description" content="Open Graph Description A" />
-  <meta property="og:url" content="https://www.url.ie/a" />
-  <meta property="og:type" content="website" />
-  <meta property="og:image" content="https://www.test.ie/og-image-a-01.jpg" />
-  <meta property="og:image:alt" content="Og Image Alt A" />
-  <meta
-    property="og:image:secure_url"
-    content="https://www.test.ie/secure-og-image-a-01.jpg"
-  />
-  <meta property="og:image:type" content="image/jpeg" />
-  <meta property="og:image:width" content="800" />
-  <meta property="og:image:height" content="600" />
-  <meta property="og:locale" content="en_IE" />
-  <meta property="og:site_name" content="SiteName A" />
-</head>
-```
-
-</details>
-
-#### 4. You don't always need to use the config
-
-The config file is just a convenience if you want to have the same meta on every page. In the case you just want a few meta tags
-on the page you can just add `<NextSeo />` without the config.
-
-For example:
-
-```jsx
-import { NextSeo } from 'next-seo';
-
-export default async function Head() {
-  return (
-    <NextSeo
-      title="No Index Example Page"
-      description="This is an example without config."
-      noindex={true}
-      useAppDir={true}
-    />
-  );
-}
-```
-
-<details>
-<summary>Output of this:</summary>
-
-```html
-<head>
-  <!-- These come from your layout -->
-  <meta charset="utf-8" />
-  <meta name="viewport" content="width=device-width" />
-  <meta name="robots" content="index,follow" />
-  <meta name="theme-color" content="#73fa97" />
-  <meta property="fb:app_id" content="1234567890" />
-
-  <!-- These come from your <NextSeo /> above -->
-  <title>No Index Example Page | Next SEO</title>
-  <meta name="robots" content="noindex,follow" />
-  <meta name="description" content="This is an example without config." />
-  <meta property="og:title" content="No Index Example Page | Next SEO" />
-  <meta
-    property="og:description"
-    content="This is an example without config."
-  />
-</head>
-```
-
-</details>
-
-#### 5. Using JSON-LD components
-
-As mentioned in the key changes, inline `<script>` can not be added via `head.js` at the moment. We can however add them via `page.js`. So to add
-a JSON-LD component from `next-seo` you just need to import it as normal add it via your page rather than the head.
-
-**IMPORTANT**: Notice the new prop `useAppDir`. This is important as it makes `next-seo` JSON-LD components use the app directory compatible version.
-
-Here is an example of adding `<ArticleJsonLd />` to a page.
-
-```jsx
-// app/jsonld/article/page.js
-import { ArticleJsonLd } from 'next-seo';
-
-const Article = () => (
-  <>
-    <h1>Article</h1>
-    <p>Inspect page for output.</p>
-    <ArticleJsonLd
-      useAppDir={true}
-      url="https://example.com/article"
-      title="Article headline"
-      images={[
-        'https://example.com/photos/1x1/photo.jpg',
-        'https://example.com/photos/4x3/photo.jpg',
-        'https://example.com/photos/16x9/photo.jpg',
-      ]}
-      datePublished="2015-02-05T08:00:00+08:00"
-      dateModified="2015-02-05T09:00:00+08:00"
-      authorName={[
-        {
-          name: 'Jane Blogs',
-          url: 'https://example.com',
-        },
-        {
-          name: 'Mary Stone',
-          url: 'https://example.com',
-        },
-      ]}
-      publisherName="Kali Skye"
-      publisherLogo="https://www.example.com/photos/logo.jpg"
-      description="This is a mighty good description of this article."
-      isAccessibleForFree={true}
-    />
-  </>
-);
-
-export default Article;
-```
-
-and if you want to modify the meta tags:
-
-```jsx
-// app/jsonld/article/head.js
-export default async function Head() {
-  return (
-    <>
-      <title>Article JSON-LD</title>
-    </>
-  );
-}
-```
-
-<details>
-<summary>Output of head for this</summary>
-
-```html
-<head>
-  <!-- These come from your layout -->
-  <meta charset="utf-8" />
-  <meta name="viewport" content="width=device-width" />
-  <meta name="robots" content="index,follow" />
-  <meta name="theme-color" content="#73fa97" />
-  <meta property="fb:app_id" content="1234567890" />
-
-  <!-- These come from your head.js above -->
-  <title>Article JSON-LD</title>
-</head>
-```
-
-</details>
-
-and then the page output in `<body>`
-
-<details>
-<summary>Output of body for this</summary>
-
-```html
-<div>
-  <h1>Article</h1>
-  <p>Inspect page for output.</p>
-  <script type="application/ld+json">
-    {
-      "@context": "https://schema.org",
-      "@type": "Article",
-      "datePublished": "2015-02-05T08:00:00+08:00",
-      "description": "This is a mighty good description of this article.",
-      "mainEntityOfPage": {
-        "@type": "WebPage",
-        "@id": "https://example.com/article"
-      },
-      "headline": "Article headline",
-      "image": [
-        "https://example.com/photos/1x1/photo.jpg",
-        "https://example.com/photos/4x3/photo.jpg",
-        "https://example.com/photos/16x9/photo.jpg"
-      ],
-      "dateModified": "2015-02-05T09:00:00+08:00",
-      "author": [
-        {
-          "@type": "Person",
-          "name": "Jane Blogs",
-          "url": "https://example.com"
-        },
-        {
-          "@type": "Person",
-          "name": "Mary Stone",
-          "url": "https://example.com"
-        }
-      ],
-      "publisher": {
-        "@type": "Organization",
-        "name": "Kali Skye",
-        "logo": {
-          "@type": "ImageObject",
-          "url": "https://www.example.com/photos/logo.jpg"
-        }
-      },
-      "isAccessibleForFree": true
-    }
-  </script>
-</div>
-```
-
-</details>
-
-### Feedback
-
-Hopefully this gets you up and running with the new app directory.
-
-If you have any feedback be sure to let me know over [here](https://github.com/garmeeh/next-seo/discussions/1073)
-
-The examples above can be found the example app in this repo [here](https://github.com/garmeeh/next-seo/tree/master/e2eWithApp)
+[Main documentation has now been updated](README.md)
diff --git a/README.md b/README.md
index 0bdbe00..8d24b6f 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,5 @@
 # Next SEO
 
-[![All Contributors](https://img.shields.io/badge/all_contributors-15-orange.svg?style=flat-square)](#contributors)
 ![npm](https://img.shields.io/npm/dw/next-seo?style=flat-square)
 
 Next SEO is a plugin that makes managing your SEO easier in Next.js projects.
@@ -12,19 +11,29 @@ looking for inspiration on what to add.
 
 It takes a lot of time to maintain an open source project so any small contribution is greatly appreciated.
 
-**Web3**: [next-seo.wallet](https://unstoppabledomains.com/d/next-seo.wallet) (ERC20 & SOL)
-
 Coffee fuels coding ☕️
 
 <a href="https://www.buymeacoffee.com/garmeeh" target="_blank"><img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" style="height: 60px !important;width: 217px !important;" ></a>
 
----
+[next-seo.wallet](https://unstoppabledomains.com/d/next-seo.wallet) (ERC20 & SOL)
 
-## Using Next.js app directory introduced in Next.js 13?
+**Note on app directory**
 
-If you are using Next.js app directory beta then it is important that you read the dedicated [documentation](APP_DIRECTORY.md)
+This note is only relevant if using the `app` directory.
 
----
+For standard meta data (eg: <meta>, <title>) then it is highly recommended that you use the built in `generateMetaData` method. You can check out the docs [here](https://beta.nextjs.org/docs/guides/seo#usage)
+
+For JSON-LD then the only change needed is you should add `useAppDir={true}` to the JSON-LD component in use. You should add use this component in your `page.js` and NOT your `head.js`.
+
+```
+<ArticleJsonLd
+  useAppDir={true}
+  url="https://example.com/article"
+  title="Article headline" <- required for app directory
+  />
+```
+
+If you are using **`pages`** directory then `NextSeo` is **exactly what you need** for your SEO needs!
 
 ### Table of Contents
 
@@ -116,6 +125,16 @@ yarn add next-seo
 
 ### Add SEO to Page
 
+---
+
+**Using Next.js app directory introduced in Next.js 13?**
+
+If you are using Next.js app directory then it is highly recommended that you use the built in `generateMetaData` method. You can check out the docs [here](https://beta.nextjs.org/docs/guides/seo#usage)
+
+If you are using `pages` directory then `NextSeo` is exactly what you need for your SEO needs!
+
+---
+
 Then you need to import `NextSeo` and add the desired properties. This will render out the tags in the `<head>` for SEO. At a bare minimum, you should add a title and description.
 
 **Example with just title and description:**
@@ -1058,6 +1077,8 @@ Next SEO now has the ability to set JSON-LD a form of structured data. Structure
 
 Google has excellent content on JSON-LD -> [HERE](https://developers.google.com/search/docs/data-types/article)
 
+**If using app directory then please ensure to add `useAppDir={false}` prop and that you are using the component in the `page.js`**
+
 Below you will find a very basic page implementing each of the available JSON-LD types:
 
 - [Article](#article-1)
@@ -1107,6 +1128,7 @@ const Page = () => (
   <>
     <h1>Article JSON-LD</h1>
     <ArticleJsonLd
+      useAppDir={false}
       url="https://example.com/article"
       title="Article headline"
       images={[
@@ -1184,6 +1206,9 @@ export default Page;
 | `itemListElements.name`     | The title of the breadcrumb displayed for the user.                                                      |
 | `itemListElements.item`     | The URL to the webpage that represents the breadcrumb.                                                   |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 ### Blog
 
 ```jsx
@@ -1306,6 +1331,9 @@ export default Page;
 | `instructions.name` | The name of the instruction step.                                   |
 | `instructions.text` | The directions of the instruction step.                             |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 ### Sitelinks Search Box
 
 ```jsx
@@ -1342,6 +1370,9 @@ export default Page;
 | `potentialActions.target`     | For websites, the URL of the handler that should receive and handle the search query; for apps, the URI of the intent handler for your search engine that should handle queries |
 | `potentialActions.queryInput` | Placeholder used in target, gets substituted for user given query                                                                                                               |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 Read the [documentation](https://developers.google.com/search/docs/appearance/structured-data/sitelinks-searchbox)
 
 ### Course
@@ -1381,6 +1412,9 @@ export default Page;
 | ------------- | ------------------------------- |
 | `providerUrl` | The url to the course provider. |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 ### Dataset
 
 ```jsx
@@ -1413,6 +1447,9 @@ export default Page;
 | --------- | ------------------------------- |
 | `license` | The url to the course provider. |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 ### Corporate Contact
 
 ```jsx
@@ -1472,6 +1509,9 @@ export default Page;
 | `contactPoint.email`             | Email asscosiated with the business`                                                                       |
 | `gecontactPointo.contactOption`  | Details about the phone number. Example `"TollFree"`                                                       |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 ### FAQ Page
 
 ```jsx
@@ -1506,6 +1546,9 @@ export default Page;
 | `mainEntity.questionName`       | The full text of the question. For example, "How long is the delivery time?". |
 | `mainEntity.acceptedAnswerText` | The full answer to the question.                                              |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 ### How-to
 
 ```jsx
@@ -1562,6 +1605,9 @@ export default Page;
 | `tool`          | An object used (but not consumed) when performing instructions or a direction.                                                           |
 | `totalTime`     | The total time required to perform all instructions or directions (including time to prepare the supplies), in ISO 8601 duration format. |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 ### Job Posting
 
 ```jsx
@@ -1644,6 +1690,9 @@ export default Page;
 | `experienceRequirements.educational.credentialCategory`         | The level of education that's required for the job posting. Use one of the following: `high school`, `associate degree`, `bachelor degree`, `professional certificate`, `postgraduate degree`                                                           |
 | `experienceRequirements.experienceInPlaceOfEducation`           | Boolean: If set to true, this property indicates whether a job posting will accept experience in place of its formal educational qualifications. If set to true, you must include both the experienceRequirements and educationRequirements properties. |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 ### Local Business
 
 Local business is supported with a sub-set of properties.
@@ -1842,6 +1891,9 @@ Local business is supported with a sub-set of properties.
 | `action`                                            | An action performed by a direct agent and indirect participants upon a direct object.                                                                |
 | `action.target`                                     | Indicates a target EntryPoint for an Action.                                                                                                         |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 **NOTE:**
 
 Images are recommended for most of the types that you can use for `LocalBusiness`, if in doubt you should add an image. You can check your generated JSON over at Google's [Structured Data Testing Tool](https://search.google.com/structured-data/testing-tool)
@@ -1869,6 +1921,9 @@ export default Page;
 | `url`    | The URL of the website associated with the logo. [Logo guidelines](https://developers.google.com/search/docs/data-types/logo#definitions) |
 | `logo`   | URL of a logo that is representative of the organization.                                                                                 |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 ### Product
 
 ```jsx
@@ -1989,6 +2044,9 @@ The property `aggregateOffer` is also available:
 | `offerCount` | The number of offers for the product.                                                                                                                           |
 | `offers`     | An offer to transfer some rights to an item or to provide a service. You can provide this as a single object, or an array of objects with the properties below. |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 More info on the product data type can be found [here](https://developers.google.com/search/docs/data-types/product).
 
 ### Social Profile
@@ -2025,6 +2083,9 @@ export default Page;
 | `url`    | The URL for the person's or organization's official website.                              |
 | `sameAs` | An array of URLs for the person's or organization's official social media profile page(s) |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 **Google Supported Social Profiles**
 
 - Facebook
@@ -2134,6 +2195,9 @@ export default Page;
 | `publication`          | If your video is happening live and you want to be eligible for the LIVE badge.          |
 | `regionsAllowed`       | The regions where the video is allowed.                                                  |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 ### VideoGame
 
 ```jsx
@@ -2221,6 +2285,9 @@ export default Page;
 | -------- | ---------------------------- |
 | `name`   | The title of the video game. |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 [More information about the schema](https://schema.org/VideoGame)
 
 ### Event
@@ -2306,6 +2373,9 @@ export default Page;
 | `endDate`   | The end date time of the event in iso8601 format           |
 | `location`  | Location of the event, can be `Place` or `VirtualLocation` |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 **`Place` type**
 Requires `address` property and `name`.
 
@@ -2445,6 +2515,9 @@ export default Page;
 | ------------ | ------------------------------------------------------------------------------------------------------ |
 | `mainEntity` | The Question for this page must be nested under the mainEntity property of the QAPageJsonld component. |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 **`mainEntity` Required properties**
 
 | Property                              | Info                                                                                                                          |
@@ -2530,6 +2603,9 @@ export default Page;
 | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
 | `hasPart.creativeWork` | The most generic kind of [creative work](https://schema.org/CreativeWork), including books, movies, photographs, software programs, etc |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 **`creativeWork` Required properties**
 
 | Property                             | Info                                                                                                                                                                                                                        |
@@ -2593,6 +2669,9 @@ export default Page;
 | -------------- | ---------------------------------------------------------------------------------------------- |
 | `lastReviewed` | Date on which the content on this web page was last reviewed for accuracy and/or completeness. |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 For reference and more info check [Profile Page DataType](https://schema.org/ProfilePage)
 
 ### Carousel
@@ -2604,6 +2683,9 @@ For reference and more info check [Profile Page DataType](https://schema.org/Pro
 | `type`   | The type of carousel                                               |
 | `data`   | The data in the form of an array for the item list in the carousel |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 #### Default (Summary List)
 
 ```jsx
@@ -2955,6 +3037,9 @@ export default () => (
 | `aggregateRating` | The average review score of the app. (Not required if review is present.) |
 | `review`          | A single review of the app. (Not required if aggregateRating is present.) |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 **Data Recommended properties**
 
 | Property              | Info                              |
@@ -3045,6 +3130,9 @@ export default () => (
 | `contactPoint.availableLanguage` | Details about the language spoken. Example `"English"` or `["English", "French"]`                          |
 | `contactPoint.email`             | Email asscosiated with the business`                                                                       |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 For reference and more info check [Docs](https://schema.org/Organization)
 
 ### Brand
@@ -3086,6 +3174,9 @@ export default () => (
 | `aggregateRating.reviewCount` | The count of total number of reviews.                                                    |
 | `aggregateRating.bestRating`  | The highest value allowed in this rating system. If bestRating is omitted, 5 is assumed. |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 For reference and more info check [Docs](https://schema.org/Brand)
 
 ### WebPage
@@ -3125,6 +3216,9 @@ export default () => (
 | `reviewedBy.type` | People or organizations that will review the content of the web page.                                |
 | `reviewedBy.name` | Name of the entity that have reviewed the content on this web page for accuracy and/or completeness. |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 For reference and more info check [Docs](https://schema.org/WebPage)
 
 ### Image Metadata
@@ -3170,6 +3264,9 @@ export default Image;
 | `license`            | A URL to a page that describes the license governing an image's use. For example, it could be the terms and conditions that you have on your website.   |
 | `acquireLicensePage` | A URL to a page where the user can find information on how to license that image.                                                                       |
 
+**Other**
+| `useAppDir` | This should be set to true if using new app directory. Not required if outside of app directory. |
+
 For reference and more info check [Google Docs](https://developers.google.com/search/docs/appearance/structured-data/image-license-metadata)
 
 ## Contributors
diff --git a/src/jsonld/product.tsx b/src/jsonld/product.tsx
index c59b41e..f99fe14 100644
--- a/src/jsonld/product.tsx
+++ b/src/jsonld/product.tsx
@@ -39,6 +39,7 @@ export interface ProductJsonLdProps extends JsonLdProps {
   purchaseDate?: string;
   releaseDate?: string;
   award?: string;
+  category?: string
 }
 
 function ProductJsonLd({
diff --git a/src/meta/buildTags.tsx b/src/meta/buildTags.tsx
index 0560ea1..0c7065a 100644
--- a/src/meta/buildTags.tsx
+++ b/src/meta/buildTags.tsx
@@ -119,13 +119,13 @@ const buildTags = (config: BuildTagsParams) => {
   }
 
   const noindex =
-    config.noindex ||
-    defaults.noindex ||
-    config.dangerouslySetAllPagesToNoIndex;
+    config.noindex != null
+      ? config.noindex
+      : config.dangerouslySetAllPagesToNoIndex || defaults.noindex;
   const nofollow =
-    config.nofollow ||
-    defaults.nofollow ||
-    config.dangerouslySetAllPagesToNoFollow;
+    config.nofollow != null
+      ? config.nofollow
+      : config.dangerouslySetAllPagesToNoFollow || defaults.nofollow;
 
   let robotsParams = '';
   if (config.robotsProps) {
@@ -152,13 +152,6 @@ const buildTags = (config: BuildTagsParams) => {
   }
 
   if (noindex || nofollow) {
-    if (config.dangerouslySetAllPagesToNoIndex) {
-      defaults.noindex = true;
-    }
-    if (config.dangerouslySetAllPagesToNoFollow) {
-      defaults.nofollow = true;
-    }
-
     tagsToRender.push(
       <meta
         key="robots"


Test patch:
diff --git a/src/meta/__tests__/buildTags.spec.tsx b/src/meta/__tests__/buildTags.spec.tsx
index 4922896..3ecca75 100644
--- a/src/meta/__tests__/buildTags.spec.tsx
+++ b/src/meta/__tests__/buildTags.spec.tsx
@@ -923,7 +923,7 @@ it('correctly sets nofollow default', () => {
     'meta[content="index,follow"]',
   );
   const noindexnofollow = container.querySelectorAll(
-    'meta[content="noindex,nofollow"]',
+    'meta[content="index,nofollow"]',
   );
 
   expect(Array.from(indexfollow).length).toBe(0);
@@ -945,8 +945,8 @@ it('correctly read noindex & nofollow false', () => {
     'meta[content="noindex,nofollow"]',
   );
 
-  expect(Array.from(indexfollow).length).toBe(0);
-  expect(Array.from(noindexnofollow).length).toBe(1);
+  expect(Array.from(indexfollow).length).toBe(1);
+  expect(Array.from(noindexnofollow).length).toBe(0);
 });
 
 it('correctly read all robots props', () => {