Repository: garmeeh/next-seo
Pull request #117 (2019-11-11 23:06:50)

Separate nofollow from noindex tag
## Description of Change(s):

According to Google SEO Specs for the [`robots` meta tag](https://developers.google.com/search/reference/robots_meta_tag), `noindex` and `nofollow` values can be set separately. Currently, settings `no-index` automatically also sets `nofollow` as observed https://github.com/garmeeh/next-seo/issues/77. A real world example is a website with an internal directory of links that the dev wants google to crawl but not index (no one wants the directory page to show up on the Google Search Results Page). Currently there is no good way of doing this in Next SEO.

This PR separates the two into their own props. As updated in the readme the behavior will be as follows: 


| `noindex` | `nofollow` | `meta` content of `robots`, `googlebot` |
| ---------- | ----------- | --------------------------------------- |
| --         | --          | `index,follow` (default)            |
| false      | false       | `index,follow`                      |
| true       | --          | `noindex,follow`                        |
| true       | false       | `noindex,follow`                        |
| --         | true        | `index,nofollow`                        |
| false      | true        | `index,nofollow`                        |
| true       | true        | `noindex,nofollow`                      |



One thing that came to mind was that codebases that currently use `next-seo` and have set `noindex` to mean `noindex,nofollow` will have regression issues  because when this PR is merged and the dev updates the version on their codebase, 

```
<NextSeo noindex={true} />
``` 
will mean
```
<meta name="robots" content="noindex,follow"> //previously "noindex,nofollow"
<meta name="googlebot" content="noindex,follow"> //previously "noindex,nofollow"
```
which is necessarily not something that people might want.

Therefore we will need to mark this as a breaking change and require the user to update the above code to 

```
<NextSeo noindex={true} nofollow={true} />
``` 


Patch:
diff --git a/.all-contributorsrc b/.all-contributorsrc
index 1e4183f..615f345 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -130,6 +130,16 @@
       "contributions": [
         "code"
       ]
+    },
+    {
+      "login": "petertulala",
+      "name": "Peter Tulala",
+      "avatar_url": "https://avatars1.githubusercontent.com/u/613623?v=4",
+      "profile": "https://github.com/petertulala",
+      "contributions": [
+        "code",
+        "test"
+      ]
     }
   ],
   "contributorsPerLine": 7
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 82cfb99..bea1682 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -1,3 +1,3 @@
 {
-  "cSpell.words": ["noindex"]
+  "cSpell.words": ["noindex", "nofollow"]
 }
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 6c2c1bc..0c099a8 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -14,8 +14,9 @@ yarn install
 ```
 
 2. Make your modifications / additions
-3. Write / Update Tests. End to end tests are required for all changes and new features.
-4. Open pull request
+3. Update / Add Documentation
+4. Write / Update Tests. End to end tests are required for all changes and new features.
+5. Open pull request
 
 ## Working with next-seo
 
diff --git a/README.md b/README.md
index 0be8016..a503bf4 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 # Next SEO
 
-[![All Contributors](https://img.shields.io/badge/all_contributors-12-orange.svg?style=flat-square)](#contributors)
+[![All Contributors](https://img.shields.io/badge/all_contributors-13-orange.svg?style=flat-square)](#contributors)
 
 Next SEO is a plugin that makes managing your SEO easier in Next.js projects.
 
@@ -24,6 +24,8 @@ Version One docs can be found [here](https://github.com/garmeeh/next-seo/tree/su
     - [Title Template](#title-template)
     - [No Index](#no-index)
     - [dangerouslySetAllPagesToNoIndex](#dangerouslysetallpagestonoindex)
+    - [No Follow](#no-follow)
+    - [dangerouslySetAllPagesToNoFollow](#dangerouslysetallpagestonofollow)
     - [Twitter](#twitter)
     - [facebook](#facebook)
     - [Canonical URL](#canonical-url)
@@ -235,12 +237,12 @@ From now on all of your pages will have the defaults above applied.
 | `titleTemplate`                    | string                  | Allows you to set default title template that will be added to your title [More Info](#title-template)                                                                               |
 | `title`                            | string                  | Set the meta title of the page                                                                                                                                                       |
 | `noindex`                          | boolean (default false) | Sets whether page should be indexed or not [More Info](#no-index)                                                                                                                    |
+| `nofollow`                         | boolean (default false) | Sets whether page should be followed or not [More Info](#no-follow)                                                                                                                  |
 | `description`                      | string                  | Set the page meta description                                                                                                                                                        |
 | `canonical`                        | string                  | Set the page canonical url                                                                                                                                                           |
 | `mobileAlternate.media`            | string                  | Set what screen size the mobile website should be served from                                                                                                                        |
 | `mobileAlternate.href`             | string                  | Set the mobile page alternate url                                                                                                                                                    |
-| `languageAlternate.hrefLang`       | string                  | Set the language of the alternate url                                                                                                                                                |
-| `languageAlternate.href`           | string                  | Set the alternate language page url                                                                                                                                                  |
+| `languageAlternate`                | array                   | Set the language of the alternate urls. Excepts object: `{ hrefLang: string, href: string }`                                                                                         |
 | `additionalMetaTags`               | array                   | Allows you to add a meta tag that is not documented here. [More Info](#additional-meta-tags)                                                                                         |
 | `twitter.cardType`                 | string                  | The card type, which will be one of `summary`, `summary_large_image`, `app`, or `player`                                                                                             |
 | `twitter.site`                     | string                  | @username for the website used in the card footer                                                                                                                                    |
@@ -287,9 +289,9 @@ titleTemplate = '%s | Next SEO';
 
 #### No Index
 
-Setting this to `true` will set `no-index`, `no-follow`. This works on a page by page basis.
+Setting this to `true` will set `noindex,follow` (to set `nofollow`, please refer to [`nofollow`](#noFollow)). This works on a page by page basis. This property works in tandem with the `nofollow` property and together they populate the `robots` and `googlebot` meta tags.
 
-So this property is a little different than all the others in the sense that setting it as a default does not work as expected. This is due to the fact Next SEO already has a default of `index` as it is an SEO plugin after all. So if you want to globally set `noindex` please see [dangerouslySetAllPagesToNoIndex](#dangerouslySetAllPagesToNoIndex)
+**Note:** The `noindex` and the [`nofollow`](#noFollow) properties are a little different than all the others in the sense that setting them as a default does not work as expected. This is due to the fact Next SEO already has a default of `index,follow` because `next-seo` is a SEO plugin after all. So if you want to globally these properties, please see [dangerouslySetAllPagesToNoIndex](#dangerouslySetAllPagesToNoIndex) and [dangerouslySetAllPagesToNoFollow](#dangerouslySetAllPagesToNoFollow).
 
 **Example No Index on a single page:**
 
@@ -305,6 +307,11 @@ export default () => (
     <p>This page is no indexed</p>
   </>
 );
+
+/* 
+<meta name="robots" content="noindex,follow">
+<meta name="googlebot" content="noindex,follow">
+*/
 ```
 
 #### dangerouslySetAllPagesToNoIndex
@@ -313,6 +320,49 @@ It has the prefix of `dangerously` because it will `noindex` all pages. As this
 
 The only way to unset this, is by removing the prop from the `DefaultSeo` in your custom `<App>`.
 
+#### No Follow
+
+Setting this to `true` will set `index,nofollow` (to set `noindex`, please refer to [`noindex`](#noIndex)). This works on a page by page basis. This property works in tandem with the `noindex` property and together they populate the `robots` and `googlebot` meta tags.
+
+**Note:** The `noindex` and the [`nofollow`](#noFollow) properties are a little different than all the others in the sense that setting them as a default does not work as expected. This is due to the fact Next SEO already has a default of `index,follow` because `next-seo` is a SEO plugin after all. So if you want to globally these properties, please see [dangerouslySetAllPagesToNoIndex](#dangerouslySetAllPagesToNoIndex) and [dangerouslySetAllPagesToNoFollow](#dangerouslySetAllPagesToNoFollow).
+
+**Example No Follow on a single page:**
+
+If you have a single page that you want no indexed you can achieve this by:
+
+```jsx
+import React from 'react';
+import NextSeo from 'next-seo';
+
+export default () => (
+  <>
+    <NextSeo nofollow={true} />
+    <p>This page is not followed</p>
+  </>
+);
+
+/* 
+<meta name="robots" content="index,nofollow">
+<meta name="googlebot" content="index,nofollow">
+*/
+```
+
+#### dangerouslySetAllPagesToNoFollow
+
+It has the prefix of `dangerously` because it will `nofollow` all pages. As this is an SEO plugin, that is kinda dangerous action. It is **not** bad to use this, just please be sure you want to `nofollow` **EVERY** page. You can still override this at a page level if you have a use case to `follow` a page. This can be done by setting `nofollow: false`.
+
+The only way to unset this, is by removing the prop from the `DefaultSeo` in your custom `<App>`.
+
+| `noindex` | `nofollow` | `meta` content of `robots`, `googlebot` |
+| --------- | ---------- | --------------------------------------- |
+| --        | --         | `index,follow` (default)                |
+| false     | false      | `index,follow`                          |
+| true      | --         | `noindex,follow`                        |
+| true      | false      | `noindex,follow`                        |
+| --        | true       | `index,nofollow`                        |
+| false     | true       | `index,nofollow`                        |
+| true      | true       | `noindex,nofollow`                      |
+
 #### Twitter
 
 Twitter will read the `og:title`, `og:image` and `og:description` tags for their card, this is why `next-seo` omits `twitter:title`, `twitter:image` and `twitter:description` so not to duplicate.
@@ -1177,6 +1227,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
     <td align="center"><a href="https://ermakov.io"><img src="https://avatars0.githubusercontent.com/u/301917?v=4" width="100px;" alt="Dmitry Ermakov"/><br /><sub><b>Dmitry Ermakov</b></sub></a><br /><a href="https://github.com/garmeeh/next-seo/commits?author=zetoke" title="Code">💻</a></td>
     <td align="center"><a href="https://github.com/duckranger"><img src="https://avatars0.githubusercontent.com/u/2087890?v=4" width="100px;" alt="Nimo Naamani"/><br /><sub><b>Nimo Naamani</b></sub></a><br /><a href="https://github.com/garmeeh/next-seo/commits?author=duckranger" title="Documentation">📖</a></td>
     <td align="center"><a href="https://github.com/calvinvoo2"><img src="https://avatars2.githubusercontent.com/u/12223423?v=4" width="100px;" alt="Calvin Ng Tjioe"/><br /><sub><b>Calvin Ng Tjioe</b></sub></a><br /><a href="https://github.com/garmeeh/next-seo/commits?author=calvinvoo2" title="Code">💻</a></td>
+    <td align="center"><a href="https://github.com/petertulala"><img src="https://avatars1.githubusercontent.com/u/613623?v=4" width="100px;" alt="Peter Tulala"/><br /><sub><b>Peter Tulala</b></sub></a><br /><a href="https://github.com/garmeeh/next-seo/commits?author=petertulala" title="Code">💻</a> <a href="https://github.com/garmeeh/next-seo/commits?author=petertulala" title="Tests">⚠️</a></td>
   </tr>
 </table>
 
diff --git a/pull_request_template.md b/pull_request_template.md
index a760432..e0febd0 100644
--- a/pull_request_template.md
+++ b/pull_request_template.md
@@ -2,6 +2,14 @@
 
 ---
 
-Please have a read of the Contributing Guide before submitting a pull request.
+Some things to help get a PR reviewed and merged faster:
+
+- Have you updated the documentation to go with your changes?
+- Have you written or updated unit tests?
+- Have you written an integration test in the test app supplied?
+
+The above are generally required on all PR's.
+
+Please have a read of the Contributing Guide for full details.
 
 https://github.com/garmeeh/next-seo/blob/master/CONTRIBUTING.md
diff --git a/src/meta/buildTags.tsx b/src/meta/buildTags.tsx
index 5214607..6a00eb4 100644
--- a/src/meta/buildTags.tsx
+++ b/src/meta/buildTags.tsx
@@ -4,6 +4,7 @@ import { BuildTagsParams } from '../types';
 const defaults = {
   templateTitle: '',
   noindex: false,
+  nofollow: false,
   defaultOpenGraphImageWidth: 0,
   defaultOpenGraphImageHeight: 0,
   defaultOpenGraphVideoWidth: 0,
@@ -26,26 +27,40 @@ const buildTags = (config: BuildTagsParams) => {
     tagsToRender.push(<title key="title">{updatedTitle}</title>);
   }
 
-  if (config.noindex === false) {
-    tagsToRender.push(
-      <meta key="robots" name="robots" content="index,follow" />,
-    );
-    tagsToRender.push(
-      <meta key="googlebot" name="googlebot" content="index,follow" />,
-    );
-  } else if (
+  const noindex =
     config.noindex ||
     defaults.noindex ||
-    config.dangerouslySetAllPagesToNoIndex
-  ) {
+    config.dangerouslySetAllPagesToNoIndex;
+  const nofollow =
+    config.nofollow ||
+    defaults.nofollow ||
+    config.dangerouslySetAllPagesToNoFollow;
+
+  if (noindex || nofollow) {
     if (config.dangerouslySetAllPagesToNoIndex) {
       defaults.noindex = true;
     }
+    if (config.dangerouslySetAllPagesToNoFollow) {
+      defaults.nofollow = true;
+    }
+
     tagsToRender.push(
-      <meta key="robots" name="robots" content="noindex,nofollow" />,
+      <meta
+        key="robots"
+        name="robots"
+        content={`${noindex ? 'noindex' : 'index'},${
+          nofollow ? 'nofollow' : 'follow'
+        }`}
+      />,
     );
     tagsToRender.push(
-      <meta key="googlebot" name="googlebot" content="noindex,nofollow" />,
+      <meta
+        key="googlebot"
+        name="googlebot"
+        content={`${noindex ? 'noindex' : 'index'},${
+          nofollow ? 'nofollow' : 'follow'
+        }`}
+      />,
     );
   } else {
     tagsToRender.push(
@@ -77,15 +92,17 @@ const buildTags = (config: BuildTagsParams) => {
     );
   }
 
-  if (config.languageAlternate) {
-    tagsToRender.push(
-      <link
-        rel="alternate"
-        key="languageAlternate"
-        hrefLang={config.languageAlternate.hrefLang}
-        href={config.languageAlternate.href}
-      />,
-    );
+  if (config.languageAlternates && config.languageAlternates.length > 0) {
+    config.languageAlternates.forEach(languageAlternate => {
+      tagsToRender.push(
+        <link
+          rel="alternate"
+          key={`languageAlternate-${languageAlternate.hrefLang}`}
+          hrefLang={languageAlternate.hrefLang}
+          href={languageAlternate.href}
+        />,
+      );
+    });
   }
 
   if (config.twitter) {
diff --git a/src/meta/defaultSEO.tsx b/src/meta/defaultSEO.tsx
index c181cf9..58b09c4 100644
--- a/src/meta/defaultSEO.tsx
+++ b/src/meta/defaultSEO.tsx
@@ -10,6 +10,7 @@ export default class extends Component<DefaultSeoProps, {}> {
       title,
       titleTemplate,
       dangerouslySetAllPagesToNoIndex = false,
+      dangerouslySetAllPagesToNoFollow = false,
       description,
       canonical,
       facebook,
@@ -21,7 +22,7 @@ export default class extends Component<DefaultSeoProps, {}> {
       defaultOpenGraphVideoWidth,
       defaultOpenGraphVideoHeight,
       mobileAlternate,
-      languageAlternate,
+      languageAlternates,
     } = this.props;
 
     return (
@@ -30,6 +31,7 @@ export default class extends Component<DefaultSeoProps, {}> {
           title,
           titleTemplate,
           dangerouslySetAllPagesToNoIndex,
+          dangerouslySetAllPagesToNoFollow,
           description,
           canonical,
           facebook,
@@ -41,7 +43,7 @@ export default class extends Component<DefaultSeoProps, {}> {
           defaultOpenGraphVideoWidth,
           defaultOpenGraphVideoHeight,
           mobileAlternate,
-          languageAlternate,
+          languageAlternates,
         })}
       </Head>
     );
diff --git a/src/meta/nextSEO.tsx b/src/meta/nextSEO.tsx
index f2e2c04..6908715 100644
--- a/src/meta/nextSEO.tsx
+++ b/src/meta/nextSEO.tsx
@@ -8,6 +8,7 @@ export default class extends Component<NextSeoProps, {}> {
     const {
       title,
       noindex = false,
+      nofollow,
       description,
       canonical,
       openGraph,
@@ -16,7 +17,7 @@ export default class extends Component<NextSeoProps, {}> {
       additionalMetaTags,
       titleTemplate,
       mobileAlternate,
-      languageAlternate,
+      languageAlternates,
     } = this.props;
 
     return (
@@ -24,6 +25,7 @@ export default class extends Component<NextSeoProps, {}> {
         {buildTags({
           title,
           noindex,
+          nofollow,
           description,
           canonical,
           facebook,
@@ -32,7 +34,7 @@ export default class extends Component<NextSeoProps, {}> {
           twitter,
           titleTemplate,
           mobileAlternate,
-          languageAlternate,
+          languageAlternates,
         })}
       </Head>
     );
diff --git a/src/types.ts b/src/types.ts
index 644ac0e..3cb8feb 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -104,10 +104,11 @@ export interface NextSeoProps {
   title?: string;
   titleTemplate?: string;
   noindex?: boolean;
+  nofollow?: boolean;
   description?: string;
   canonical?: string;
   mobileAlternate?: MobileAlternate;
-  languageAlternate?: LanguageAlternate;
+  languageAlternates?: ReadonlyArray<LanguageAlternate>;
   openGraph?: OpenGraph;
   facebook?: { appId: string };
   twitter?: Twitter;
@@ -116,10 +117,10 @@ export interface NextSeoProps {
 
 export interface DefaultSeoProps extends NextSeoProps {
   dangerouslySetAllPagesToNoIndex?: boolean;
+  dangerouslySetAllPagesToNoFollow?: boolean;
   defaultOpenGraphImageWidth?: number;
   defaultOpenGraphImageHeight?: number;
   defaultOpenGraphVideoWidth?: number;
   defaultOpenGraphVideoHeight?: number;
 }
-
 export interface BuildTagsParams extends DefaultSeoProps, NextSeoProps {}


Test patch:
diff --git a/e2e/next-seo.config.ts b/e2e/next-seo.config.ts
index efd8b4c..255efa7 100644
--- a/e2e/next-seo.config.ts
+++ b/e2e/next-seo.config.ts
@@ -11,10 +11,12 @@ const APP_DEFAULT_SEO: DefaultSeoProps = {
     media: 'only screen and (max-width: 640px)',
     href: 'https://m.canonical.ie',
   },
-  languageAlternate: {
-    hrefLang: 'de-AT',
-    href: 'https://www.canonical.ie/de',
-  },
+  languageAlternates: [
+    {
+      hrefLang: 'de-AT',
+      href: 'https://www.canonical.ie/de',
+    },
+  ],
   openGraph: {
     type: 'website',
     locale: 'en_IE',
diff --git a/e2e/pages/overridden.tsx b/e2e/pages/overridden.tsx
index c939099..3772f41 100644
--- a/e2e/pages/overridden.tsx
+++ b/e2e/pages/overridden.tsx
@@ -6,13 +6,16 @@ export default () => (
   <>
     <NextSeo
       noindex={true}
+      nofollow={true}
       title="Title B"
       description="Description B"
       canonical="https://www.canonical.ie/b"
-      languageAlternate={{
-        hrefLang: 'de-AT',
-        href: 'https://www.canonical.ie/de',
-      }}
+      languageAlternates={[
+        {
+          hrefLang: 'de-AT',
+          href: 'https://www.canonical.ie/de',
+        },
+      ]}
       mobileAlternate={{
         media: 'only screen and (max-width: 640px)',
         href: 'https://m.canonical.ie',
diff --git a/src/meta/__tests__/__snapshots__/buildTags.spec.tsx.snap b/src/meta/__tests__/__snapshots__/buildTags.spec.tsx.snap
index d3606e4..c0cbd00 100644
--- a/src/meta/__tests__/__snapshots__/buildTags.spec.tsx.snap
+++ b/src/meta/__tests__/__snapshots__/buildTags.spec.tsx.snap
@@ -483,6 +483,11 @@ exports[`renders correctly 1`] = `
     hreflang="de-AT"
     rel="alternate"
   />
+  <link
+    href="https://www.canonical.ie/sk"
+    hreflang="sk-SK"
+    rel="alternate"
+  />
   <meta
     content="summary_large_image"
     name="twitter:card"
diff --git a/src/meta/__tests__/buildTags.spec.tsx b/src/meta/__tests__/buildTags.spec.tsx
index 5be9f92..569698e 100644
--- a/src/meta/__tests__/buildTags.spec.tsx
+++ b/src/meta/__tests__/buildTags.spec.tsx
@@ -16,10 +16,16 @@ const SEO: BuildTagsParams = {
     media: 'only screen and (max-width: 640px)',
     href: 'https://m.canonical.ie',
   },
-  languageAlternate: {
-    hrefLang: 'de-AT',
-    href: 'https://www.canonical.ie/de',
-  },
+  languageAlternates: [
+    {
+      hrefLang: 'de-AT',
+      href: 'https://www.canonical.ie/de',
+    },
+    {
+      hrefLang: 'sk-SK',
+      href: 'https://www.canonical.ie/sk',
+    },
+  ],
   openGraph: {
     type: 'website',
     locale: 'en_IE',
@@ -157,23 +163,28 @@ it('returns full array for default seo object', () => {
     `link[media="${SEO.mobileAlternate.media}"]`,
   );
 
-  const languageAlternateTag = container.querySelectorAll(
+  expect(Array.from(mobileAlternateTag).length).toBe(1);
+  expect(Array.from(mobileAlternateHref).length).toBe(1);
+  expect(Array.from(mobileAlternateMedia).length).toBe(1);
+
+  const languageAlternatesTags = container.querySelectorAll(
     'link[rel="alternate"][hrefLang]',
   );
-  const languageAlternateHref = container.querySelectorAll(
-    `link[href="${SEO.languageAlternate.href}"]`,
-  );
-  const languageAlternateHrefLang = container.querySelectorAll(
-    `link[hrefLang="${SEO.languageAlternate.hrefLang}"]`,
+  expect(Array.from(languageAlternatesTags).length).toBe(
+    SEO.languageAlternates.length,
   );
 
-  expect(Array.from(mobileAlternateTag).length).toBe(1);
-  expect(Array.from(mobileAlternateHref).length).toBe(1);
-  expect(Array.from(mobileAlternateMedia).length).toBe(1);
+  SEO.languageAlternates.forEach((languageAlternate, idx) => {
+    const languageAlternateHref = container.querySelectorAll(
+      `link[href="${SEO.languageAlternates[idx].href}"]`,
+    );
+    const languageAlternateHrefLang = container.querySelectorAll(
+      `link[hrefLang="${SEO.languageAlternates[idx].hrefLang}"]`,
+    );
 
-  expect(Array.from(languageAlternateTag).length).toBe(1);
-  expect(Array.from(languageAlternateHref).length).toBe(1);
-  expect(Array.from(languageAlternateHrefLang).length).toBe(1);
+    expect(Array.from(languageAlternateHref).length).toBe(1);
+    expect(Array.from(languageAlternateHrefLang).length).toBe(1);
+  });
 
   expect(title).toBeDefined();
   expect(Array.from(index).length).toBe(2);
@@ -214,7 +225,7 @@ it('returns full array for default seo object', () => {
   expect(Array.from(canonicalTag).length).toBe(1);
 });
 
-it('correctly sets noindex, nofollow', () => {
+it('correctly sets noindex', () => {
   const overrideProps = {
     ...SEO,
     noindex: true,
@@ -222,14 +233,49 @@ it('correctly sets noindex, nofollow', () => {
   const tags = buildTags(overrideProps);
   const { container } = render(<>{React.Children.toArray(tags)}</>);
   const index = container.querySelectorAll('meta[content="index,follow"]');
-  const noindex = container.querySelectorAll(
-    'meta[content="noindex,nofollow"]',
-  );
+  const noindex = container.querySelectorAll('meta[content="noindex,follow"]');
 
   expect(Array.from(index).length).toBe(0);
   expect(Array.from(noindex).length).toBe(2);
 });
 
+it('correctly sets nofollow', () => {
+  const overrideProps = {
+    ...SEO,
+    nofollow: true,
+  };
+  const tags = buildTags(overrideProps);
+  const { container } = render(<>{React.Children.toArray(tags)}</>);
+  const indexfollow = container.querySelectorAll(
+    'meta[content="index,follow"]',
+  );
+  const indexnofollow = container.querySelectorAll(
+    'meta[content="index,nofollow"]',
+  );
+
+  expect(Array.from(indexfollow).length).toBe(0);
+  expect(Array.from(indexnofollow).length).toBe(2);
+});
+
+it('correctly sets noindex, nofollow', () => {
+  const overrideProps = {
+    ...SEO,
+    noindex: true,
+    nofollow: true,
+  };
+  const tags = buildTags(overrideProps);
+  const { container } = render(<>{React.Children.toArray(tags)}</>);
+  const indexfollow = container.querySelectorAll(
+    'meta[content="index,follow"]',
+  );
+  const noindexnofollow = container.querySelectorAll(
+    'meta[content="noindex,nofollow"]',
+  );
+
+  expect(Array.from(indexfollow).length).toBe(0);
+  expect(Array.from(noindexnofollow).length).toBe(2);
+});
+
 it('displays title with titleTemplate integrated', () => {
   const template = 'Next SEO';
   const overrideProps = {
@@ -738,27 +784,50 @@ it('correctly sets noindex default', () => {
   };
   const tags = buildTags(overrideProps);
   const { container } = render(<>{React.Children.toArray(tags)}</>);
-  const index = container.querySelectorAll('meta[content="index,follow"]');
-  const noindex = container.querySelectorAll(
+  const indexfollow = container.querySelectorAll(
+    'meta[content="index,follow"]',
+  );
+  const noindexfollow = container.querySelectorAll(
+    'meta[content="noindex,follow"]',
+  );
+
+  expect(Array.from(indexfollow).length).toBe(0);
+  expect(Array.from(noindexfollow).length).toBe(2);
+});
+
+it('correctly sets nofollow default', () => {
+  const overrideProps = {
+    ...SEO,
+    dangerouslySetAllPagesToNoFollow: true,
+  };
+  const tags = buildTags(overrideProps);
+  const { container } = render(<>{React.Children.toArray(tags)}</>);
+  const indexfollow = container.querySelectorAll(
+    'meta[content="index,follow"]',
+  );
+  const noindexnofollow = container.querySelectorAll(
     'meta[content="noindex,nofollow"]',
   );
 
-  expect(Array.from(index).length).toBe(0);
-  expect(Array.from(noindex).length).toBe(2);
+  expect(Array.from(indexfollow).length).toBe(0);
+  expect(Array.from(noindexnofollow).length).toBe(2);
 });
 
-it('correctly read noindex false', () => {
+it('correctly read noindex & nofollow false', () => {
   const overrideProps = {
     ...SEO,
     noindex: false,
+    nofollow: false,
   };
   const tags = buildTags(overrideProps);
   const { container } = render(<>{React.Children.toArray(tags)}</>);
-  const index = container.querySelectorAll('meta[content="index,follow"]');
-  const noindex = container.querySelectorAll(
+  const indexfollow = container.querySelectorAll(
+    'meta[content="index,follow"]',
+  );
+  const noindexnofollow = container.querySelectorAll(
     'meta[content="noindex,nofollow"]',
   );
 
-  expect(Array.from(index).length).toBe(2);
-  expect(Array.from(noindex).length).toBe(0);
+  expect(Array.from(indexfollow).length).toBe(0);
+  expect(Array.from(noindexnofollow).length).toBe(2);
 });