Install and configure Optimizely Graph on your site
How to install and configure content synchronization from Optimizely Content Management System as part of the Optimizely Graph service.
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
.
Note
Optimizely 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.com
for 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
.
Note
The 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 synchronization package settings 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="" />
<add key="optimizely__contentgraph__appkey" value="" />
<add key="optimizely__contentgraph__secret" value="" />
<add key="optimizely__contentgraph__singlekey" value="" />
<add key="optimizely__contentgraph__allowsendinglog" value="true"/>
The older settings format is still supported but is deprecated.
<add key="optimizely:gatewayaddress" value="" />
<add key="optimizely:query.appkey" value="" />
<add key="optimizely:query.secret" value="" />
<add key="optimizely:query.singlekey" value="" />
<add key="optimizely:allowsendinglog" value="true"/>
Configure the synchronization package settings in ASP.NET Core
Open appsettings.json
and add your settings to configure your account.
"Optimizely": {
"ContentGraph": {
"GatewayAddress": "",
"AppKey": "",
"Secret": "",
"SingleKey": "",
"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 for now
//services.AddContentGraph(_configuration);
If you already use 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. The,n 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
});
IncludeInternalContentRoots
andIncludeSiteHosts
– Set totrue
to sync information on content roots and site definitions to Optimizely Graph.EnablePreviewFeatures
– Set totrue
if you want beta features in Content Delivery to be enabled for more data in Optimizely Graph.- (Optional)
SetValidateTemplateForContentUrl
– Set totrue
to only provide URLs for content with CMS templates. If not, the URL is null.
Property indexing 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.
Important
To improve query performance, you should use
OutputOnly
mode 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
.
Note
Configuration set in
startup.cs
overridesappsettings.json
.
appsettings.json
"Optimizely": {
"ContentGraph": {
"Include": {
"ContentIds": [],
"ContentTypes": []
},
"OnlySyncContentTypesInWhitelistToSchema": false
}
}
startup.cs
:
services.AddContentGraph(configureOptions: options =>
{
options.Include.ContentIds = new int[3] { 1, 2, 3 };
options.Include.ContentTypes = new string[2] { typeof(StandardPage).Name, typeof(ProductPage).Name };
});
ContentIds
– Array of content Ids (an array of integers) that syncs contents whose Ids exist in theContentIds
array and the content whose ancestor Ids exist in theContentIds
array.ContentTypes
– Array of contentType names (an array of strings) that syncs content whoseContentTypes
exist in theContentTypes
array.OnlySyncContentTypesInWhitelistToSchema
– By default, content types are included in Optimizely Graph GraphQL's schema. If you want only the content types listed inInclude.ContentTypes
to be in the GraphQL schema, setOnlySyncContentTypesInWhitelistToSchema
totrue
.
Configuration options rules
ContentIds = []
andContentTypes = []
– Content is synced as normal.ContentIds = []
andContentTypes != []
– Only the content whoseContentTypeID
matches in theContentTypes
or in the descendants that are inherited directly or indirectly from theContentTypes
are synced.Note
If the values in
ContentTypes
do not exist in the Optimizely Content Management System (CMS), you cannot sync content.ContentIds != []
andContentTypes = []
– Two types of content can be synced.- Content whose Ids exist in
ContentIds
are synchronized. - Content whose ancestor Ids exist in
ContentIds
are synced.Note
You cannot sync content if no content exists in
ContentIds
.
- Content whose Ids exist in
ContentIds != []
andContentTypes != []
– Two types of content can be synced.- Content whose Ids exist in
ContentIds
andContentTypeID
matches in theContentTypes
or in the descendants that are inherited directly or indirectly from theContentTypes
are synced. - Content whose ancestor Ids exist in
ContentIds
and whoseContentTypeID
matches in theContentTypes
or in the descendants that are inherited directly or indirectly from theContentTypes
are 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
ContentTypes
array and their descendants that are inherited directly or indirectly from theContentTypes
array.
Configure sync version content
"Optimizely": {
   "ContentGraph": {
       "ContentVersionSyncMode": "DraftAndPublishedOnly"
   }
}
To determine which version contents 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
, if the content is modified, other referencing content can be resynced to Optimizely Graph.
To enable this, set SyncReferencingContents
to true
in appsettings.json
. The default value is false. Also, set IndexReferencingContents
to true.
If the number of referencing content is large, resyncing can take long after the related content is updated. You should set the setting to false
and wait for Optimizely Graph's scheduled synchronization job to run again instead.
"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 are the following:
PropertyContentArea
PropertyContentAreaItem
PropertyContentReference
PropertyContentReferenceList
PropertyLinkItem
PropertyLinkCollection
PropertyPageReference
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 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 inlining contents 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
XhtmlString
You 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 front end to render the rich text to your target platform (mobile, web, Windows, or Mac applications).
Note
RichTextFormat.Html
andRichTextFormat.HtmlAndStructured
has 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 XhtmlString
as 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.RichTextFormat
configuration requires you to re-run the synchronization 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
RichTextFormat
configuration must beStructured
orHtmlAndStructured
(see previous). - Add the
RichTextStructAsJson
setting."Optimizely": { "ContentGraph": { "RichTextStructAsJson": true } }
- Run the indexing job.
Note
The default type for
structure
isstring
. But when using this feature, its type changes toobject
. You must update your frontend site to handle both types for thestructure
field of theXhtmlString
.
Configure Date
to DateTime
Date
to DateTime
By 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
}
}
Note
This configuration is not applied to the
_modified
field. It is alwaysDate
.
Configuration to prevent field collision
By default, this feature is disabled. To enable it, complete the following:
- Change the
PreventFieldCollision
setting."Optimizely": { "ContentGraph": { "PreventFieldCollision": true } }
- Reset the account and run the indexing job. See Reset account functionality.
Note
This feature only works from version >= 3.7.0.
When this feature is enabled and you want to change the DateTime type (from
Date
toDateTime
or 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.cs
add the following:services.AddContentGraph(configureOptions: options => { options.MarkRequiredPropertiesToGraph = true; //default is false });
- Set the Required attribute 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 5 days ago