Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

Dev guideRecipesAPI ReferenceChangelog
Dev guideRecipesUser GuidesNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Configure CMS 12 to send content

Learn how to configure Optimizely Content Management System 12 (CMS 12) to send content from your site to external systems or services.

Optimizely Optimizely Graph integrates with Content Management System 12 (CMS 12) to automatically sync content changes. This guide covers set up, configuration, and best practices for CMS integration.

Architecture Overview

The data flow between Optimizely CMS and Optimizely Graph works as follows:

  1. Authoring – A content editor creates, updates, moves, or deletes content in Optimizely CMS.
  2. Event capture – CMS integration package listens for content lifecycle events, such as SavedContent, PublishedContent, MovedContent, DeletedContent, or ExpiredContent.
  3. Serialization – The integration serializes the changed content into JSON that matches Optimizely Graph schema.
  4. Transfer – The serialized content is securely sent to Optimizely Graph Gateway over HTTPS.
  5. Processing – The gateway validates, enriches, and indexes the content into Optimizely Graph.
  6. Availability – The content is queryable through Optimizely Graph GraphQL API by websites, applications, or other services.

Installation

  1. Install NuGet Package

    • Package Manager Console: Install-Package Optimizely.ContentGraph.Cms
    • .NET CLI: dotnet add package Optimizely.ContentGraph.Cms
    • PackageReference in .csproj: <PackageReference Inclide ="Optimizely.ContentGraph.Cms"Version="version_number" />
  2. Verify Package Installation

    Ensure your project file (.csproj) contains the package reference stated previously

Configuration

appsettings.json example:

{
  "Optimizely": {
    "ContentGraph": {
      "GatewayAddress": "https://cg.optimizely.com",
      "AppKey": "your-hmac-app-key",
      "Secret": "your-hmac-secret-key",
      "SingleKey": "your-single-key-for-public-access",
      "BufferedIndexingGracePeriod": 10000,
      "PreventFieldCollision": true
    }
  }
}

Configuration Properties

  • GatewayAddress – Optimizely Graph Gateway endpoint URL
  • AppKey – HMAC authentication public key
  • Secret – HMAC authentication secret key
  • SingleKey – Simple authentication key for read-only access
  • AllowSendingLog – Enable detailed logging
  • MaxBatchSize - Maximum items per batch (default 300)
  • BufferedIndexingGracePeriod – Grace period in ms for batching (default 0)
  • ExtractMedia – Enable text extraction from media files (default true)
  • PreventFieldCollision – Prevent GraphQL field collisions (default false)
  • MarkRequiredPropertiesToGraph – Mark required fields in Graph schema (default false)

CMS Setup

Basic Configuration in Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddContentDeliveryApi();
    services.AddContentGraph();
    services.AddMvc();
    services.AddCms();
}
📘

Note

Always call AddContentDeliveryApi() before AddContentGraph().

Advanced Configuration

public void ConfigureServices(IServiceCollection services)
{
    services.AddContentDeliveryApi();
    
    services.AddContentGraph(options =>
    {
        // Schema Configuration
        options.PreventFieldCollision = true;
        options.IncludeInheritanceInContentType = true;
        options.MarkRequiredPropertiesToGraph = true;
        
        // Content Expansion Settings
        options.ExpandLevel.ContentArea = 2;      // Expand ContentAreas 2 levels deep
        options.ExpandLevel.Default = 0;          // Don't expand other references
        options.ExpandLevel.ContentReference = 1; // Expand ContentReference 1 level
        
        // Batching Configuration
        options.BufferedIndexingGracePeriod = 10000; // 10 seconds in milliseconds
        options.MaxBatchSize = 50;
        
        // Media extraction
        options.ExtractMedia = true;
        
        // Preview Configuration
        options.Events.OnGeneratingPreviewUrl = context =>
        {
            // Custom preview URL generation
            var previewUrl = $"/preview?id={context.ContentReference}&token={GeneratePreviewToken(context)}";
            context.UpdateUrl(new Uri(previewUrl, UriKind.RelativeOrAbsolute));
            return Task.CompletedTask;
        };
    });
    
    // Configure event indexing behavior
    services.Configure<EventIndexingOptions>(options =>
    {
        options.IndexReferencingContent = ReferencingPropertyTypes.Inlined;
        options.SyncContentsInParallelTaskAndForget = false; // Set to false for synchronous processing
    });
}

Content Type Mapping

1. Automatic Mapping

Content types are automatically mapped based on your CMS content type definitions:

[ContentType(DisplayName = "Article Page", GUID = "...")]
public class ArticlePage : PageData
{
    [Required]
    public virtual string Heading { get; set; }
    [UIHint(UIHint.Textarea)]
    public virtual XhtmlString ArticleBody { get; set; }
    public virtual DateTime? Published { get; set; }
    public virtual ContentReference Author { get; set; }
    public virtual IList<string> Categories { get; set; }
    public virtual ContentReference FeaturedImage { get; set; }
    public virtual ContentArea RelatedArticles { get; set; }
}

Generated Graph Schema Example:

{
  "ArticlePage": {
    "properties": {
      "Heading": { "type": "String!" },
      "ArticleBody": { "type": "LongString" },
      "Published": { "type": "Date" },
      "Author": { "type": "ContentReference" },
      "Categories": { "type": "StringArray" },
      "FeaturedImage": { "type": "ContentReference" },
      "RelatedArticles": { "type": "[ContentAreaItemModelSearch]" }
    }
  }
}

2. Custom Field Mapping

Content field mapping is handled through CMS integration package's internal mechanisms. Field exclusion and type mapping are controlled through the configuration options in the AddContentGraph() method using the events system:

[ContentType(DisplayName = "Product Page")]
public class ProductPage : PageData
{
    // Fields are automatically mapped based on their .NET types
    // Use configuration events to exclude fields if needed
    public virtual string InternalNotes { get; set; }
    
    public virtual string ProductCode { get; set; }
    
    public virtual decimal Price { get; set; }
    
    public virtual ContentArea ProductImages { get; set; }
}