Install and configure Optimizely Graph on your site
How to install and configure content sync from Optimizely Content Management System as part of the Optimizely Graph service.
Optimizely Graph is a powerful, unified content query and delivery service that lets you access and reuse content across Optimizely products through a single GraphQL API. It enables flexible data retrieval, high-performance search, and dynamic content delivery for both Optimizely CMS and custom applications.
This guide explains how to install and configure Optimizely Graph for your site. For a broader understanding of Optimizely Graph concepts, API structure, schema management, and advanced configurations, see the Optimizely Graph documentation .
Install Optimizely Graph
Install Optimizely.ContentGraph.CMS in your Optimizely Content Management System (CMS) site to sync content types and content. In Visual Studio, go to Tools > Nuget Package Manager > Package Manager Console. At the console, enter install-package Optimizely.ContentGraph.Cms.
NoteOptimizely supports packages for ASP.NET with the package versions >= 2.0.
Configure Optimizely Graph for your site
Depending on your version of .NET, different methods exist to configure Optimizely Graph. The process for the different versions involves entering settings into configuration files. For that reason, gather the following information:
GatewayAddress– URL for the API gateway. This value should be set tohttps://cg.optimizely.comfor all production environments.AppKey– Sent to you when the account was created and is the public key from your HMAC authentication pair.Secret– Sent to you when the account was created and is the secret key from your HMAC authentication pair.SingleKey– Sent to you when the account was created and is the public key you can use on the public site.AllowSendingLog– Flag that lets you send errors and warnings to the API gateway. This data helps the Support team investigate when something goes wrong. Defaults totrue.
NoteThe configuration for Optimizely Graph is only needed when working with the CMS site locally. The configuration is already set in the Optimizely Digital Experience Platform (DXP) site, so do not include the configuration for the CMS site when deploying it to DXP through the PaaS portal.
Configure the sync package configuration in the .NET framework
For newer versions of the .NET platform, you can enter the settings into the web.config file in the <appSettings> section.
<add key="optimizely__contentgraph__gatewayaddress"
value="https://cg.optimizely.com" />
<add key="optimizely__contentgraph__appkey"
value="Sent to you when the account was created and is the public key from your HMAC authentication pair" />
<add key="optimizely__contentgraph__secret"
value="Sent to you when the account was created and is the secret key from your HMAC authentication pair" />
<add key="optimizely__contentgraph__singlekey"
value="Sent to you when the account was created and is the public key you can use on the public site" />
<add key="optimizely__contentgraph__allowsendinglog"
value="true" />The older settings format is still supported, but is deprecated.
<add key="optimizely:gatewayaddress"
value="https://cg.optimizely.com" />
<add key="optimizely:query.appkey"
value="Sent to you when the account was created and is the public key from your HMAC authentication pair" />
<add key="optimizely:query.secret"
value="Sent to you when the account was created and is the secret key from your HMAC authentication pair" />
<add key="optimizely:query.singlekey"
value="Sent to you when the account was created and is the public key you can use on the public site" />
<add key="optimizely:allowsendinglog"
value="true" />Configure the sync package settings in ASP.NET Core
Open appsettings.json and add your settings to configure your account.
{
"Optimizely": {
"ContentGraph": {
"GatewayAddress": "https://cg.optimizely.com",
"AppKey": "Sent to you when the account was created and is the public key from your HMAC authentication pair",
"Secret": "Sent to you when the account was created and is the secret key from your HMAC authentication pair",
"SingleKey": "Sent to you when the account was created and is the public key you can use on the public site",
"AllowSendingLog": "true"
}
}
}If you do not use the Content Delivery API in your CMS site, add the following to the ConfigureServices(IServiceCollection services) method of Startup.cs. Optimizely Graph depends on the Content Delivery API, which is the minimum configuration.
If you want to customize Content Delivery API, see the configure Content Delivery API documentation.
services.ConfigureContentApiOptions(o =>
{
o.IncludeInternalContentRoots = true;
o.IncludeSiteHosts = true;
// o.EnablePreviewFeatures = true; // optional
});
services.AddContentDeliveryApi(); // required
// For further configurations, see:
// https://docs.developers.optimizely.com/content-cloud/v1.5.0-content-delivery-api/docs/configuration
services.AddContentGraph();
// The following is obsolete and is kept for compatibility
// services.AddContentGraph(_configuration);If you already use the Content Delivery API in your application, you only need to add a line to register Optimizely Graph services.
//other configurations for Content Delivery API
services.AddContentGraph();
//the following is obsolete and is kept for compatibility for now
//services.AddContentGraph(_configuration);Set the Content Delivery options to true for the data related to site information to be synced to Optimizely Graph. Then you can query them through the SiteDefinition content-type.
services.ConfigureContentApiOptions(o =>
{
o.IncludeInternalContentRoots = true;
o.IncludeSiteHosts = true;
//o.EnablePreviewFeatures = true;//optional
//o.SetValidateTemplateForContentUrl(true);//optional
});IncludeInternalContentRootsandIncludeSiteHosts– Set totrueto sync information on content roots and site definitions to Optimizely Graph.EnablePreviewFeatures– Set totrueif you want beta features in Content Delivery to be enabled for more data in Optimizely Graph.- (Optional)
SetValidateTemplateForContentUrl– Set totrueto only provide URLs for content with CMS templates. If not, the URL is null.
Property index modes
The CMS integration with Optimizely Graph has a feature to set property indexing modes. This can be done by adding an attribute to the property in your content type class. Optimizely supports typed models.
OutputOnly mode
OutputOnly modeNot all content properties must be searchable or filterable when indexing Optimizely Graph content. You should turn off filtering and searching for these properties to reduce the load to Optimizely Graph and improve query performance.
To turn off searching and filtering for a property, set the indexing mode to OutputOnly. With this mode, the property value can still be queried and read from Optimizely Graph, but it is impossible to filter by that property using the where clause. It is also not searchable with full-text search.
ImportantTo improve query performance, you should use
OutputOnlymode on properties that you know you will not filter and search on.
[GraphProperty(PropertyIndexingMode.OutputOnly)]
public virtual string AStringProperty { get; set; }Default mode
Default modeWith Default indexing mode, the property is stored in Optimizely Graph. This means that it can be filtered using the where clause, but it is not searchable with full-text search.
[GraphProperty(PropertyIndexingMode.Default)]
public virtual string AStringProperty { get; set; }Include inheritance
To get results from inherited types when querying a content type, include inheritance in the ContentType list. Set IncludeInheritanceInContentType to true.
services.AddContentGraph(configureOptions: options =>
{
options.IncludeInheritanceInContentType = true;
});Enable extract media type
To enable extracting data from the content media type, set ExtractMedia to true. Defaults to true.
services.AddContentGraph(configureOptions: options =>
{
options.ExtractMedia = false;
});Configure allowlist content
To set what content can be synced to Optimizely Graph and prevent syncing content with sensitive data, add the Include section to the appsettings.json file or use the configuration in startup.cs.
NoteConfiguration set in
startup.csoverridesappsettings.json.
appsettings.json
{
"Optimizely": {
"ContentGraph": {
"Include": {
"ContentIds": [],
"ContentTypes": []
},
"OnlySyncContentTypesInWhitelistToSchema": false
}
}
}
startup.cs:
services.AddContentGraph(configureOptions: options =>
{
options.Include.ContentIds = new int[] { 1, 2, 3 };
options.Include.ContentTypes = new string[]
{
typeof(StandardPage).Name,
typeof(ProductPage).Name
};
});
ContentIds– Array of content Ids (an array of integers) that syncs contents whose Ids exist in theContentIdsarray and the content whose ancestor Ids exist in theContentIdsarray.ContentTypes– Array of contentType names (an array of strings) that syncs content whoseContentTypesexist in theContentTypesarray.OnlySyncContentTypesInWhitelistToSchema– By default, content types are included in Optimizely Graph GraphQL's schema. If you want only the content types listed inInclude.ContentTypesto be in the GraphQL schema, setOnlySyncContentTypesInWhitelistToSchematotrue.
Configuration options rules
ContentIds = []andContentTypes = []– Content is synced as normal.ContentIds = []andContentTypes != []– Only the content whoseContentTypeIDmatches in theContentTypesor in the descendants that are inherited directly or indirectly from theContentTypesare synced.NoteIf the values in
ContentTypesdo not exist in CMS, you cannot sync content.ContentIds != []andContentTypes = []– Two types of content can be synced.ContentIds != []andContentTypes != []– Two types of content can be synced.- Content whose Ids exist in
ContentIdsandContentTypeIDmatches in theContentTypesor in the descendants that are inherited directly or indirectly from theContentTypesare synced. - Content whose ancestor Ids exist in
ContentIdsand whoseContentTypeIDmatches in theContentTypesor in the descendants that are inherited directly or indirectly from theContentTypesare synced.
- Content whose Ids exist in
Note
- When content is synched, language versions of that content are available in Optimizely Graph.
- Content (that is linked to synced content) is synched within that synced content, regardless of any allowlist conditions that otherwise apply.
- When querying contents in GraphiQL, you can only directly query the content types that exist in the
ContentTypesarray and their descendants that are inherited directly or indirectly from theContentTypesarray.
Configure sync version content
"Optimizely": {
"ContentGraph": {
"ContentVersionSyncMode": "DraftAndPublishedOnly"
}
}To determine which versions content can be synced to Optimizely Graph, you have the following options:
DraftAndPublishedOnly(Default) – To sync the published content and draft content.PublishedOnly– To sync only the published content.All– To sync all status version content.
Configure resync of referenced content
When content is referenced by other content using ContentLink, ContentReference, LinkItem, or ContentArea, modifying the content can trigger the referencing content's resyncing to Optimizely Graph.
To enable this, set SyncReferencingContents to true in appsettings.json. The default value is false.
To enable resync of referencing content, set SyncReferencingContents to true and ensure EventIndexingOptions.Enable is set to true. Configuring ReferenceTypesToReIndex or IndexReferencingContent is optional and only required if you want to control or limit which types of referencing content are resynced.
If the number of referencing content items is large, resyncing may take a long time after the related content is updated. In that case, configure the setting to false and wait for Optimizely Graph’s scheduled sync job to run again.
"Optimizely": {
"ContentGraph": {
"SyncReferencingContents": "false"
}
}Configure resync of related content
You can specify which referencing content is resynced based on the reference type. Depending on the different sites, you can change the settings to reduce the number of resynced content.
Types of references
PropertyContentAreaPropertyContentAreaItemPropertyContentReferencePropertyContentReferenceListPropertyLinkItemPropertyLinkCollectionPropertyPageReference
To configure the setting, in startup.cs when configuring EventIndexingOptions, set the setting ReferenceTypesToReIndex.
The following example states that when a page is updated, only pages that reference this page through ContentArea or ContentAreaItem properties are resynced:
services.Configure<EventIndexingOptions>(ops =>
{
ops.ReferenceTypesToReIndex = new List<Type>()
{
typeof(PropertyContentReference),
typeof(PropertyContentAreaItem)
};
});With this configuration, only Page A and Page B are resynced, Page C and Page D are not resynced after Block X is updated.
If ReferenceTypesToReIndex is not changed, all related contents is resynced, regardless of the type of the reference property.
Another way to configure this is through appsettings.json, by setting IndexReferencingContent. The following are the three possible values:
None– Related content is not resynced.All– All related content is resynced.Inlined– Only content with references that cause the referenced content to be inlined are resynced (ContentArea,ContentAreaItem).
When IndexReferencingContent is configured, the ReferenceTypesToReIndex settings are ignored.
"Optimizely": {
"ContentGraph": {
"EventIndexing": {
"IndexReferencingContent": "Inlined"
}
}Disable inline content in the expanded field of reference properties
You can expand reference properties in the range of 0-5 for all reference types. The default is 1, and for ContentArea, it is 3. To disable expanding entirely, set the ExpandLevel to 0.
Example 1: Prevent expanding all reference types except ContentArea.
services.AddContentGraph(options =>
{
options.ExpandLevel.Default = 0;
});Example 2: Prevent expanding all reference types, including ContentArea.
services.AddContentGraph(options =>
{
options.ExpandLevel.Default = 0;
options.ExpandLevel.ContentArea = 0;
});If your site does not need to inline content in reference fields like ContentReference or LinkItem, setting the depth of expansion to 0 speeds up sync and reduces document size.
Configure sync of content type when the site starts
Open Startup.cs and add the following:
services.Configure<EventIndexingOptions>(ops =>
{
ops.SyncContentTypesOnInit = true;
});Configure to enable preview tokens for the on-page editing feature
When calling AddContentGraph, you can enable preview tokens for the on-page editing feature by setting EnablePreviewTokens to true.
You can also set the OnGeneratingPreviewUrl event to customize your content preview URL before adding the preview token as a query string parameter.
You can enable preview tokens in your Program.cs,Startup.cs, or appsettings.json.
See On-page editing and Optimizely Graph.
services.AddContentGraph(options =>
{
options.EnablePreviewTokens = true;
options.Events.OnGeneratingPreviewUrl = ctx =>
{
// ctx.UpdateUrl(new Uri("/test?id=" + ctx.ContentReference, UriKind.RelativeOrAbsolute));
return Task.CompletedTask;
};
});"Optimizely": {
"ContentGraph": {
"EnablePreviewTokens": "true"
}
}Configure the format for XhtmlString
XhtmlStringYou can fetch the rich text stored in XhtmlString in a different structured delivery format than a raw HTML string.
By default, XhtmlString is returned as a single string containing the raw HTML.
services.Configure<ContentApiOptions>(op =>
{
op.RichTextFormat = RichTextFormat.Html;
});Optimizely Graph implements headless CMS. HTML formatting is specific to the web and not headless. So you should use the RichTextFormat.Structured JSON format for rich text fields and then implement your frontend to render the rich text to your target platform (mobile, web, Windows, or Mac applications).
Note
RichTextFormat.HtmlandRichTextFormat.HtmlAndStructuredhas some limitations and unreliability when a block is added to the rich text fields.
Optimizely Graph query.
StandardPage {
items {
Name,
MainBody
}
}Response example.
"MainBody": "<p><strong>The weather is very nice !</strong></p>"Structured HTML
To return XhtmlStringas structured HTML, use the following:
services.Configure<ContentApiOptions>(op =>
{
op.RichTextFormat = RichTextFormat.Structured;
});Optimizely Graph query.
StandardPage {
items {
Name
MainBody {
Structure
}
}
}
Response example.
{
"MainBody": {
"Structure": "{\"type\":\"richText\",\"children\":[{\"type\":\"paragraph\",\"children\":[{\"text\":\"The weather is very nice !\",\"bold\":true}]}]}"
}
}
Raw and structured HTML
You can return the raw HTML and the structured HTML.
services.Configure<ContentApiOptions>(op =>
{
op.RichTextFormat = RichTextFormat.HtmlAndStructured;
});Optimizely Graph query.
StandardPage {
items {
Name,
MainBody {
Structure
Html
}
}
}Response example
{
"MainBody": {
"Structure": "{\"type\":\"richText\",\"children\":[{\"type\":\"paragraph\",\"children\":[{\"text\":\"The weather is very nice !\",\"bold\":true}]}]}",
"Html": "<p><strong>The weather is very nice !</strong></p>"
}
}
Note
- Changing the
ContentApiOptions.RichTextFormatconfiguration requires you to re-run the sync job .- The HTML elements that Optimizely has seen a mapping for are mapped, but HTML elements that Optimizely has not seen a mapping for are returned unmapped (the HTML element name).
Configuration to retrieve structure as JSON
By default, this feature is disabled. When enabled, the structure's response is similar to the following:
"MainBody": {
"Structure": {
"type": "richText",
"children": [
{
"type": "paragraph",
"children": [
{
"text": "Test"
}
]
}
]
},
"Html": "<p>Test</p>"
}To enable this feature, complete the following:
- The
RichTextFormatconfiguration must beStructuredorHtmlAndStructured(see previous). - Add the
RichTextStructAsJsonsetting."Optimizely": { "ContentGraph": { "RichTextStructAsJson": true } } - Run the indexing job.
NoteThe default type for
structureisstring. But when using this feature, its type changes toobject. You must update your frontend site to handle both types for thestructurefield of theXhtmlString.
Configure Date to DateTime
Date to DateTimeBy default, the DateTime type in the GraphQL schema is Date. You can change the type to DateTime by setting UseDateTimeGQLType to true.
"Optimizely": {
"ContentGraph": {
"UseDateTimeGQLType": true
}
}
NoteThis configuration is not applied to the
_modifiedfield. It is alwaysDate.
Configuration to prevent field collision
By default, this feature is disabled. To enable it, complete the following:
- Change the
PreventFieldCollisionsetting."Optimizely": { "ContentGraph": { "PreventFieldCollision": true } } - Reset the account and run the indexing job. See Smooth rebuild.
NoteThis feature only works in versions >= 3.7.0.
When this feature is enabled and you want to change the
DateTimetype (fromDatetoDateTimeor vice versa), you must run the indexing job again. While the job is running, the datetime fields may return null.
Configure required fields
In CMS, you can set properties to be required. This means that a value must be entered. You can get information from the GraphQL schema about which fields always have a value. See Property attributes.
To enable this feature, complete the following:
- Configure CMS to send metadata about required properties. In
startup.csadd the following:services.AddContentGraph(configureOptions: options => { options.MarkRequiredPropertiesToGraph = true; //default is false }); - Set the
Requiredattribute for the property. An example is in the Property attributes documentation.
The GraphQL query is now configured to know that the field always has a value. For information, see the blog on Required fields support in Optimizely Graph.
Updated 3 days ago