📚 Product Knowledge
Page Tree Container Pages
📖 Docs

Page Tree and Container Pages - Optimizely CMS 12

Exam Area: Content Area 1 – Product Knowledge (15%)
Source: https://academy.optimizely.com/student/path/3128969/activity/4970323
Published: Feb 16, 2026


Overview (Academy Key Points)

  • Performance anchor: The "100-item rule" prevents database latency and editorial lag.
  • Architectural split: Container pages decouple logical data storage from the visual navigation tree.
  • Multi-site logic: SiteDefinition.Current resolves current site context — avoid hard-coded IDs.
  • Inheritance control: Tree structure dictates both URL routing segments and security permissions.

1. Visual vs Logical Hierarchy (Academy – 4970323)

The page tree reflects the visual navigation structure AND the logical data structure. Sophisticated implementations separate these:


2. The "100-Item Rule" (Academy – 4970323)

Avoid more than 100 content items under a single node. Exceeding this causes:

Bucket strategies:

Date-based:       /News/2024/03/Article-Name/
Alphabetical:     /Glossary/A/Architecture/
Category folders: /Products/Electronics/ /Products/Furniture/

3. Multi-site Architecture and SiteDefinition (Academy – 4970323)

// Resolve current site context — avoid hard-coded IDs
var currentSite = SiteDefinition.Current;
var startPageLink = currentSite.StartPage;
var rootPageLink = currentSite.RootPage;
var siteName = currentSite.Name;

Site Definition requirements:


4. Container Pages (Academy – 4970323)

Container Page = page without associated rendering template → cannot be directly accessed via URL.

[ContentType(
    DisplayName = "Container Page",
    GUID = "aab97b20-1234-5678-abcd-000000000001",
    Description = "Container for organizing pages")]
[AvailableContentTypes(
    Availability = Availability.Specific,
    Include = new[] { typeof(ArticlePage), typeof(ProductPage) }
)]
public class ContainerPage : PageData
{
    // No properties — only structural/organizational
}

5. ContentReference Special Values

ContentReference.RootPage          // Root of the page tree
ContentReference.StartPage         // Start page of the site
ContentReference.GlobalBlockFolder // Global blocks folder
ContentReference.SiteBlockFolder   // Site-specific blocks folder
ContentReference.WasteBasket       // Trash / Waste Basket

6. URL Routing and Segment Generation (Academy – 4970323)

URLs are generated hierarchically from the URLSegment property of each node:


7. Permission Inheritance (Academy – 4970323)


8. AvailableContentTypes

// Specific types only
[AvailableContentTypes(Availability = Availability.Specific, Include = new[] { typeof(ArticlePage) })]
public class NewsSectionPage : PageData { }

// Pure container — nothing can be created
[AvailableContentTypes(Availability = Availability.None)]
public class ReadOnlyContainerPage : PageData { }

9. Traversing the Page Tree in Code

var children = _contentRepository.GetChildren<PageData>(parentReference);
var descendants = _contentRepository.GetDescendents(parentReference);
var ancestors = _contentRepository.GetAncestors(contentReference);

1. Page Tree

The Page Tree is the hierarchical structure of all pages in the CMS.

Root
└── Start Page (/)
    ├── About Us (/about-us/)
    │   ├── Team (/about-us/team/)
    │   └── History (/about-us/history/)
    ├── Products (/products/)
    │   ├── Product A (/products/product-a/)
    │   └── Product B (/products/product-b/)
    └── Contact (/contact/)

Characteristics:


2. Special ContentReference Values

ContentReference.RootPage           // Root of the page tree
ContentReference.StartPage          // Start page of the site
ContentReference.GlobalBlockFolder  // Blocks folder
ContentReference.SiteBlockFolder    // Site-specific blocks folder
ContentReference.WasteBasket        // Trash

3. Container Pages

A Container Page is a page without a content template (does not render HTML), used only to organize the tree structure.

Creating a Container Page type:

using EPiServer.Core;
using EPiServer.DataAbstraction;
using EPiServer.DataAnnotations;

[ContentType(
    DisplayName = "Container Page",
    GUID = "aab97b20-1234-5678-abcd-000000000001",
    Description = "Container for organizing pages")]
[AvailableContentTypes(
    Availability = Availability.Specific,
    Include = new[] { typeof(ArticlePage), typeof(ProductPage) }
)]
public class ContainerPage : PageData
{
    // No specific properties
    // Only uses built-in properties (Name, etc.)
}

Container Page Characteristics:


4. AvailableContentTypes

Controls which types of content can be created within a page:

// Allow only ArticlePage and NewsPage to be created in this section
[AvailableContentTypes(
    Availability = Availability.Specific,
    Include = new[] { typeof(ArticlePage), typeof(NewsPage) }
)]
public class NewsSectionPage : PageData { }

// Allow nothing to be created (pure container)
[AvailableContentTypes(Availability = Availability.None)]
public class ReadOnlyContainerPage : PageData { }

// Allow everything
[AvailableContentTypes(Availability = Availability.All)]
public class FlexiblePage : PageData { }

5. Structuring a Website

Typical hierarchy:

Root
├── Start Page (StartPage) – home page
│   ├── Section Container (ContainerPage)
│   │   ├── Article 1 (ArticlePage)
│   │   └── Article 2 (ArticlePage)
│   └── Product Section (ContainerPage)
│       ├── Product 1 (ProductPage)
│       └── Product 2 (ProductPage)
└── Global Assets
    ├── Shared Blocks
    └── Shared Media

6. Traversing the Page Tree in Code

// Get children of a page
var children = _contentRepository.GetChildren<PageData>(parentReference);

// Get all descendants
var descendants = _contentRepository.GetDescendents(parentReference);

// Get ancestors (breadcrumb)
var ancestors = _contentRepository.GetAncestors(contentReference);

// Get by ContentType
var articles = _contentRepository.GetChildren<ArticlePage>(sectionReference);

7. Sort Order

// SortOrder is set on the parent page
// In Admin: Properties → Settings → Sort subpages by

// In code
var startPage = _contentRepository.Get<StartPage>(ContentReference.StartPage);
// startPage.ChildOrderRule (EPiServer.Core.FilterSortOrder)

FilterSortOrder values:


8. Waste Basket


Review Questions

  1. What does the "100-item rule" warn about? (More than 100 items under one node → edit mode latency, DB stress, search overhead)
  2. What is a Container Page? (A page without a rendering template — non-navigable, used for organizing the tree structure)
  3. What is SiteDefinition.Current.StartPage used for? (Get the start page of the current site without hard-coding an ID)
  4. How does permission inheritance work in the page tree? (Inherited from parent node by default; can be broken at any node)
  5. When should you use a bucket strategy? (When content volume > 100 items — use date/category folders to distribute)
  6. Does a Container Page have a URL? (A URL is generated, but it returns 404 because there is no template)