📚 Product Knowledge
Seo
📖 Docs

SEO - Optimizely CMS 12

Exam Area: Area 1 – Product Knowledge (15%) Reference: https://docs.developers.optimizely.com/content-management-system/docs/seo


1. SEO Built-in Features

Optimizely CMS 12 includes several built-in SEO capabilities:

FeatureDescription
Friendly URLsHuman-readable page URLs from page names
Canonical URLsPrevent duplicate content via canonical link
Sitemap supportSite map can be generated (via add-on or code)
Metadata propertiesTitle, Description, Keywords on PageData
301 / 302 redirectsAutomatic redirect from old URLs when pages move
Language-specific URLsSeparate URLs per language
Open Graph supportVia custom properties or add-ons

2. URL Generation

CMS generates URLs from content names by default:

Page name:     "About Us"
Generated URL: /about-us/

Page name:     "News & Events"
Generated URL: /news-events/   (special chars stripped)

You can override the URL segment on a page:

Edit View → Properties → URL Segment field (on PageData)

3. IUrlResolver

// Resolve a ContentReference to a URL
public class LinkBuilder
{
    private readonly IUrlResolver _urlResolver;

    public LinkBuilder(IUrlResolver urlResolver)
    {
        _urlResolver = urlResolver;
    }

    public string GetUrl(ContentReference contentRef, string language = null)
    {
        return _urlResolver.GetUrl(
            contentRef,
            language,
            new VirtualPathArguments { ForceCanonical = true });
    }

    public IContent ResolveFromUrl(string url)
    {
        return _urlResolver.Route(new UrlBuilder(url));
    }
}

4. Built-in SEO Properties

// PageData includes these SEO-related properties:
public abstract class PageData
{
    // Used as <title> tag
    [Display(Name = "Page name in URL")]
    public virtual string URLSegment { get; set; }

    // Used as <meta name="keywords">
    [Display(Name = "Keywords")]
    public virtual string MetaKeywords { get; set; }

    // Used as <meta name="description">
    [Display(Name = "Description")]
    public virtual string PageDescription { get; set; }

    // Generates canonical URL
    public virtual bool ExcludedFromSearch { get; set; }
}

5. Custom SEO Properties

public class SeoPage : PageData
{
    [Display(Name = "SEO Title", Order = 300, GroupName = "SEO")]
    public virtual string SeoTitle { get; set; }

    [Display(Name = "Meta Description", Order = 310, GroupName = "SEO")]
    [StringLength(160)]
    public virtual string MetaDescription { get; set; }

    [Display(Name = "Open Graph Image", Order = 320, GroupName = "SEO")]
    [UIHint(UIHint.Image)]
    public virtual ContentReference OgImage { get; set; }

    [Display(Name = "Canonical URL", Order = 330, GroupName = "SEO")]
    public virtual Url CanonicalUrl { get; set; }
}

6. Rendering SEO Tags in Razor

@model SeoPage
@{
    var title = string.IsNullOrEmpty(Model.SeoTitle) ? Model.Name : Model.SeoTitle;
    var description = Model.MetaDescription ?? Model.PageDescription;
}

<head>
    <title>@title - My Site</title>
    <meta name="description" content="@description" />
    @if (Model.CanonicalUrl != null)
    {
        <link rel="canonical" href="@Model.CanonicalUrl" />
    }
    @if (Model.OgImage != null)
    {
        <meta property="og:image" content="@Url.ContentUrl(Model.OgImage)" />
    }
</head>

7. URL Rewriting and Redirects

When a page is moved or renamed, CMS can issue automatic redirects:

Admin → CMS → Config → Manage Website → URL Rewriting
  → Enable automatic redirects for moved/renamed pages
// Register custom URL rewrite rules
services.Configure<RedirectOptions>(options =>
{
    options.AddPermanentRedirect("/old-url/", "/new-url/");
});

8. Excluded from Search

// Mark content as excluded from search (search engines and CMS Find)
page.ExcludedFromSearch = true;

This sets <meta name="robots" content="noindex,nofollow"> if implemented in the view.


9. Sitemap.xml

CMS 12 does not include a built-in sitemap generator. Options:

  1. Add-on: EPiServer.GoogleXmlSitemap (community package)
  2. Custom implementation: Query all published pages via IContentLoader
// Simple custom sitemap endpoint
app.MapGet("/sitemap.xml", async (IContentLoader loader, IUrlResolver urlResolver) =>
{
    var pages = loader.GetDescendents(ContentReference.StartPage)
        .Select(r => loader.Get<IContent>(r))
        .OfType<PageData>()
        .Where(p => !p.ExcludedFromSearch);

    var xml = GenerateSitemapXml(pages, urlResolver);
    return Results.Content(xml, "application/xml");
});

Review Questions

  1. Which property controls the URL segment of a page? (URLSegment on PageData)
  2. What happens when a CMS page is renamed or moved (if redirects are enabled)? (CMS automatically issues a 301 redirect from the old URL to the new one)
  3. Which interface resolves content references to URLs? (IUrlResolver)
  4. What does ExcludedFromSearch = true signal? (The page should not be indexed — implementation renders noindex/nofollow meta tag)
  5. Does CMS 12 include a built-in sitemap.xml generator? (No — must be built custom or via a community add-on)