SitecoreAI (XM Cloud): Implement NoIndex & NoFollow Metadata

If you're working with SitecoreAI (XM Cloud) and Next.js, one thing you quickly realize is this:
SEO control shouldn’t depend on developers every time.
Content editors should be able to decide:
- Should this page appear on Google?
- Should search engines follow links on this page?
That’s exactly where NoIndex and NoFollow come in. In this guide, we’ll implement them in a clean, scalable, and production-ready way using Sitecore’s component-based architecture.
No unnecessary complexity - just a clean, production-ready solution that content editors can actually use.
🔍 What Are NoIndex and NoFollow?
Let’s keep it super simple:
- NoIndex → “Don’t show this page in Google search results”
- NoFollow → “Don’t follow links on this page”
Think of it like giving instructions to search engines:
“You can see this page… but don’t index or trust it.”
💡 When Should You Use Them?
| NoIndex is perfect for | NoFollow is useful for | Both together |
|---|---|---|
| Thank-you pages (after form submission) | User-generated content pages | Completely internal content |
| Draft content that's not ready for public viewing | Comment sections with untrusted links | Test pages in production |
| Duplicate content (like print-friendly versions) | Pages you don't want to pass link authority to | Temporary campaign pages |
| Internal admin or staging pages | ||
| Pages under development |
⚙️ Step 1: Create Sitecore Template Fields
First, add the NoIndex and NoFollow fields to your base template.
Using Content Editor
- Open Content Editor in SitecoreAI (XM Cloud)
- Navigate to your base template:
/sitecore/templates/Project/<Your Project Name>/_Base Metadata - Create or use an existing section called "SEO Settings"
- Add two checkbox fields
- Inherit the "_Base Metadata" template in the "Page" template so that it is available across all pages.
Using Serialization (Recommended)
Create a YAML file in your serialization directory:
# /serialization/templates/Project/<Your Project Name>/_Base Metadata.yml ID: "your-template-guid" Path: /sitecore/templates/Project/<Your Project Name>/_Base Metadata DB: master Languages: - Language: en Versions: - Version: 1 Sections: - ID: "seo-section-guid" Name: SEO Settings Fields: - ID: "noindex-field-guid" Name: NoIndex Key: noindex Type: Checkbox - ID: "nofollow-field-guid" Name: NoFollow Key: nofollow Type: Checkbox
Deploy it:
dotnet sitecore ser push
🧩 Step 2: Create Placeholder Settings
Instead of mixing meta logic with layout, we keep things clean by creating a dedicated placeholder where MetaTags will live.
In Sitecore Content Editor
- Navigate to:
/sitecore/layout/Placeholder Settings/Project/<Your Project Name> - Create a new Placeholder Settings item
- Name it:
headless-metatags - Leave Allowed Controls empty for now (we'll add MetaTags rendering in the next step)
This placeholder will be specifically for meta tag components, keeping them separate from header/main/footer content.
🧠 Step 3: Create the MetaTags Component
Create the TypeScript component that will read the fields and render the robots meta tag.
// src/components/<Your Project Name>/MetaTags.tsx import React from 'react'; import Head from 'next/head'; import { Field, ImageField } from '@sitecore-jss/sitecore-jss-nextjs'; // Component props - receives fields from Sitecore interface MetaTagsProps { fields?: { NoIndex?: Field<boolean>; NoFollow?: Field<boolean>; }; } // MetaTags Component - Renders robots meta tag based on NoIndex and NoFollow field values const MetaTags = ({ fields }: MetaTagsProps): JSX.Element | null => { // Build the robots content value const robotsContent = [ fields?.NoIndex?.value && 'noindex', fields?.NoFollow?.value && 'nofollow' ].filter(Boolean).join(','); // Don't render anything if both checkboxes are unchecked if (!robotsContent) { return null; } return ( <Head> <meta name="robots" content={robotsContent} /> </Head> ); }; export default MetaTags;
🏗️ Step 4: Register the Component in Component Factory
Add MetaTags to your component factory so Sitecore can render it.
// src/temp/componentFactory.ts import MetaTags from 'components/<Your Project Name>/MetaTags'; const components = new Map(); // Register MetaTags component components.set('MetaTags', MetaTags); // ... other components export default defaultComponentFactory(components);
🧱 Step 5: Create Sitecore Rendering Item
Create the rendering definition in Sitecore.
In Content Editor
- Navigate to:
/sitecore/layout/Renderings/Project/<Your Project Name>/Components - Right-click → Insert → Json Rendering
- Name it:
MetaTags - Set the following fields:
- Component Name: MetaTags
- Datasource Location: Leave empty (uses context item)
- Datasource Template: Leave empty (uses context item fields)
Update Placeholder Settings
- Go back to
/sitecore/layout/Placeholder Settings/Project/<Your Project Name>/headless-metatags - In Allowed Controls, add the MetaTags rendering you just created
♻️ Step 6: Create Partial Design
Partial Designs let you reuse component configurations across multiple pages.
Create the Partial Design
- Navigate to:
/sitecore/layout/Partial Designs/Project/<Your Project Name> - Create a new Partial Design item
- Name it:
MetaTags
Add MetaTags to the Partial Design
- Open the
MetaTagsPartial Design item - Click Presentation → Details
- In the layout, add the MetaTags component to the
headless-metatagsplaceholder - Click OK and Save
Now you have a reusable partial design that can be added to any page design.
🌐 Step 7: Add to Page Designs
Add the MetaTags Partial Design to your page designs so it appears on all pages.
For Each Page Design
- Navigate to:
/sitecore/layout/Layouts/Project/<Your Project Name>/[YourPageDesign] - Click Presentation → Details
- Click Edit on the Default device
- In the Partial Designs section, add the
MetaTagsPartial Design - Click OK and Save
Repeat this for all your page designs (Home, Content Page, Landing Page, etc.).
🧩 Step 8: Update Layout.tsx
Your Layout component already has the placeholder ready
The key line is:// src/Layout.tsx import React from 'react'; import Head from 'next/head'; import { Placeholder, LayoutServiceData, Field, } from '@sitecore-jss/sitecore-jss-nextjs'; interface LayoutProps { layoutData: LayoutServiceData; } interface RouteFields { [key: string]: unknown; Title?: Field; MetaTitle?: Field; } const Layout = ({ layoutData }: LayoutProps): JSX.Element => { const { route } = layoutData.sitecore; const fields = route?.fields as RouteFields; return ( <> <Head> <title> {fields?.MetaTitle?.value?.toString() || fields?.Title?.value?.toString() || 'Default Title'} </title> <link rel="icon" href="/favicon.ico" /> </Head> {/* MetaTags component renders here via placeholder */} {route && <Placeholder name="headless-metatags" rendering={route} />} <div> <header> /*Your header code*/ </header> <main> /*Your main code*/ </main> <footer> /*Your footer code*/ </footer> </div> </> ); }; export default Layout;
{route && <Placeholder name="headless-metatags" rendering={route} />}
🤔 Why Placeholder + Partial Design?
You might wonder why we use this architecture instead of hardcoding the component. Here's why:
- Content Editor Control - Editors can theoretically remove/add MetaTags per page
- Reusability - Partial Design makes it easy to add to new page designs
- Consistency - All Sitecore components work the same way
- Experience Editor - Component shows up properly in Experience Editor
- Flexibility - Easy to create page-specific overrides if needed
⚡Wrapping Up
You now have a complete, production-ready NoIndex/NoFollow implementation using Sitecore's component architecture
✨ What we built:
- Sitecore template fields for NoIndex and NoFollow
- Dedicated
headless-metatagsplaceholder - Reusable MetaTags component
- Partial Design for easy deployment
- Clean, maintainable TypeScript code
- Full content editor control
Now your content editors have full control over search engine indexing without touching code