Programmatic Content Management
Outline
- Goal: Create and update CMS content via code for automation, integrations, and repeatable workflows.
-
Core APIs:
IContentLoader(read),IContentRepository(write),CreateWritableClone()(immutability rule). - Typical scenarios: Create pages, update blocks from external systems, create language variants, and control publish states.
- Operational note: Programmatic writes affect versioning, approvals, and often indexing - treat bulk changes as release-grade operations.
Introduction
In modern CMS implementations, content rarely lives in one place. You may need to synchronise data from external systems, generate pages at scale, run scheduled updates, or implement controlled publishing workflows. Optimizely CMS 12 provides APIs that make these scenarios possible without relying on manual editor actions for every change.
This page walks through common scenario patterns for creating and updating content programmatically in a CMS 12 (PaaS) solution. The examples focus on repeatable, safe patterns that align with Optimizely's versioning and security model.
1. Core concepts to keep straight
Most scenario-based implementations boil down to three rules: use the right interface for intent, clone before you modify, and choose the right SaveAction based on your workflow.
-
IContentLoaderis for reading. Prefer it forGet<T>,GetItems, andGetChildren. -
IContentRepositoryis for writing. Use it forGetDefault<T>,Save,Delete, andMove. -
CreateWritableClone()is non-negotiable when updating existing items.
Read vs write mental model
Select a topic to expand and read the details.
A quick mental model (read vs write) ▼
- If your method should never change content, inject
IContentLoader. - If your method can change content, inject
IContentRepository(and still useIContentLoaderfor reads). - Updates are always: load → clone → modify → save.
2. Scenario 1: Creating a new page programmatically
Page creation typically happens in imports, synchronisation jobs, or "generate pages from a dataset" flows. The stable approach is GetDefault<T>(parent) → set properties → Save with the correct action.
Steps to create and publish a page
Select a topic to expand and read the details.
Expand: Steps to create and publish a page ▼
- Identify the parent
ContentReference. - Create the instance via
GetDefault<T>. - Set typed properties (preferred) or properties via the
Propertycollection. - Save with the
SaveActionthat matches the workflow (draft, request approval, publish).
Important: If you're generating many pages, include logging and a rollback plan. In large batches, failures are inevitable - surprises shouldn't be.
3. Scenario 2: Updating an existing block based on external data
Integration-driven updates are a classic load → clone → modify → save loop. The key discipline is to keep reads on IContentLoader, and only switch to IContentRepository when you save.
Hardening an external-data update
Select a topic to expand and read the details.
Hardening an external-data update ▼
- Validate the payload: treat external input as untrusted; apply business rules before saving.
- Be explicit about state: consider draft saves for changes that require review.
- Make updates idempotent: repeated runs should not create unintended changes.
- Log with identifiers: log content IDs and correlation IDs from the external system.
4. Scenario 3: Creating content in a specific language
Multilingual creation is the same pattern as page creation, with one difference: the language version is created by calling GetDefault<T>(parent, culture).
Language version gotchas
Select a topic to expand and read the details.
Language version gotchas ▼
- Fallback isn't creation: fallback loading finds content; it doesn't create missing language versions.
- Keep naming conventions consistent: avoid "same page, different name" chaos across locales.
- Workflow alignment: localised content often needs approval gates per market and team.
5. Scenario 4: Managing publishing status (draft vs published vs scheduled)
Publishing control is expressed via SaveAction. The important part is to be deliberate: draft saves are not a "lesser publish" - they are a workflow decision.
Choosing the right SaveAction
Select a topic to expand and read the details.
Choosing the right SaveAction ▼
-
SaveAction.Savekeeps it as a draft (not live). -
SaveAction.RequestApprovalis for workflows with reviewers and approvers. -
SaveAction.Publishmakes the version live immediately. -
SaveAction.CheckIn | SaveAction.Schedulemoves content into delayed publish. -
Use caution: flags like
ForceCurrentVersioncan overwrite version history.
6. Best practices for scenario-based operations
- Wrap operations in guardrails: validate inputs, enforce business rules, and fail fast on invalid data.
-
Be explicit with permissions: choose
AccessLevelto match the action (edit vs publish). - Log like you'll need it later: content IDs, external identifiers, version references, and the exact action taken.
- Plan for scale: bulk writes can cause indexing load and longer processing time - batch and schedule responsibly.
- Prefer deterministic behaviour: avoid "works locally" drift by keeping versions aligned and processes repeatable.
Conclusion
Programmatic content creation and updates are core to automation, integration, and controlled delivery in Optimizely CMS 12. When you consistently apply the patterns in this page - read with IContentLoader, modify with writable clones, and save with deliberate SaveAction choices - you get predictable outcomes without undermining versioning, workflow, or security.
