All Collections
Content Management
Optimizely (v12) installation guide
Optimizely (v12) installation guide

This is a developer's guide to configuring the Frontify integration for Optimizely.

Updated over a week ago

This is the installation guide for Optimizely version 12. If you use Optimizely version 11, please take a look at this installation guide.

The Frontify Integration for Optimizely enables you to browse brand assets managed in the Frontify DAM without ever leaving the Optimizely environment and add those assets to Optimizely.

This connector supports EPiServer.CMS.UI (≥ 12.18.0 && < 13.0.0). Please see the full dependency details here.


Get the latest integration version from this link and follow the configuration steps below.

1. Startup.cs

To get started with the plugin, you need to register it to the solutions service collection by adding


to the startup.cs which is normally located in the solution's root.

2. Appsenting.json

The appsettings.json file is an application configuration file that stores configuration settings. You can find it in the root of the code solution.

"Frontify": {
"ClientId": "[GUID]", // Your Frontify Client Id
"Domain": "", // [Optional] Frontify domain to show in the Frontify Finder
"RootFolderId": 218, // Optimizely media folder id where assets are stored. This id should reflect an existing content id of a folder in media pane in Optimizely CMS
"EnableOnAllImages": true, // If Frontify attribute should be applied on all media properties
"AllowedTypes": ".jpg,.jpeg,.jpe,.gif,.bmp,.png,.gif,.psd", // Allowed image extensions
"PreferredDownloadWidth": 1600, // Default width of downloaded assets, by default, this image will not be used except for the Episerver UI
"DefaultTinyMceImageWidth": 600, //default max image width in RichEditor after import
"" // Optional Url to specific Frontify Finder version

For more information about appsettings.json, visit this link.

It's also possible to implement and register an instance of the IFrontifySettings (or extended IFrontifyCommerceSettings) interface to take full control of all settings, for instance, configuring which metadata to synchronize.

3. Configuring additional settings

You need to implement the IFrontifyMedia interface on a content type that inherits from the Optimizely ImageData class in your solution. This will enable some additional fields that are used by the addon to keep the assets in sync with the original in Frontify.

public interface IFrontifyMedia: IContentData

/// <summary>
/// Frontify alternative text
/// </summary>
string FrontifyAltText { get; set; }

/// <summary>
/// Frontify description
/// </summary>
string FrontifyDescription { get; set; }

/// <summary>
/// Frontify CDN url
/// </summary>
string FrontifyUrl { get; set; }

/// <summary>
/// Frontify preview CDN url
/// </summary>
string FrontifyPreviewUrl { get; set; }

/// <summary>
/// Frontify JSON metadata
/// </summary>
string FrontifyJson { get; set; }

/// <summary>
/// Frontify modified date
/// </summary>
DateTime FrontifyModifiedDate { get; set; }

Example of implementation:

[ContentType(GUID = "0A89E464-56D4-449F-AEA8-2BF774AB8730")]
[MediaDescriptor(ExtensionString = "jpg,jpeg,jpe,ico,gif,bmp,png")]
public class ImageFile : ImageData, IFrontifyMedia
/// <summary>
/// Gets or sets the copyright.
/// </summary>
/// <value>
/// The copyright.
/// </value>
public virtual string Copyright { get; set; }

public virtual string Description { get; set; }

public virtual string AltText { get; set; }

// IFrontifyMedia properties

[Display(GroupName = FrontifyGroupNames.Frontify)]
public virtual string FrontifyUrl { get; set; }

[Display(GroupName = FrontifyGroupNames.Frontify)]
public virtual string FrontifyPreviewUrl { get; set; }

[Display(GroupName = FrontifyGroupNames.Frontify)]
public virtual string FrontifyJson { get; set; }

[Display(GroupName = FrontifyGroupNames.Frontify)]
public virtual DateTime FrontifyModifiedDate { get; set; }

public string FrontifyAltText
get => this.GetPropertyValue(p => p.AltText);
set => this.SetPropertyValue(p => p.AltText, value);

public string FrontifyDescription
get => this.GetPropertyValue(p => p.Description);
set => this.SetPropertyValue(p => p.Description, value);

(The FrontifyModifiedDate property is used to keep track of when the asset was last changed in Frontify.)

For more information about Optimizely Media types, please visit this link.

4. Add to your Tiny MCE configuration toolbar

For the button to show up in Tiny MCE (the rich editor in Optimizely), search for TinyMceConfiguration in your solution and add: frontify-insert-media to your toolbar.

You can find the document here.


services.Configure<TinyMceConfiguration>(config =>
"epi-link epi-image-editor epi-dnd-processor epi-personalized-content preview searchreplace autolink directionality visualblocks visualchars fullscreen image link media template codesample table charmap pagebreak nonbreaking anchor insertdatetime advlist lists " +
"wordcount help code")
"bold italic strikethrough forecolor | epi-link image epi-image-editor epi-personalized-content | frontify-insert-media | bullist numlist | searchreplace fullscreen ",
"styleselect blocks | alignleft aligncenter alignright alignjustify | removeformat | table toc | code"
, "");

5. Decorate your Optimizely property with the Frontify UIHint

[UIHint(FrontifyUiHint.FrontifyImage)] //minimal implementation
public virtual ContentReference ImageAsContentReference { get; set; } //for ContentReference property

[UIHint(FrontifyUiHint.FrontifyImageUrl)] //minimal implementation
public virtual Url ImageAsUrl { get; set; } //for Url-property

[FrontifyConfiguration(DisableDefaultOptimizelyMedia = true)]
public virtual ContentReference ImageAsContentReference { get; set; }

[FrontifyConfiguration(ImageWidth = 500)] //image will be 500 width in TinyMCE XHtmlString
public virtual XhtmlString MainBody { get; set; }

[FrontifyConfiguration(QueryParameters = "width=300&height=300&format=webp&quality=75")]//image will be 300 width x 300 height in TinyMCE XHtmlString
public virtual XhtmlString MainBody { get; set; }

This will replace the Optimizely built-in Image editor with an extended one that supports selecting images from Frontify as well as local Optimizely images.

Make sure frontifyimage.cshtml and FrontifyImageUrl.cshtml are installed into Views/Shared/DisplayTemplates. These will be utilized when FrontifyUiHint is used.

The attribute should be used in combination with FrontifyUiHint.Parameters for FrontifyConfiguration are:

  • DisableDefaultOptimizelyMedia - If you want to turn off the default Optimizely Media Selector, the default is false

  • QueryParameters - Additional query string appended to CDN imageurl import into XHtmlString (TinyMCE), e.g., width=100&height=300&format=webp&quality=75; this parameter can not be combined with ImageWidth

  • ImageWidth - Default Imagewidth imported into XHtmlString (TinyMCE), QueryParameters will override this value

6. Controlling the structure of downloaded assets in Optimizely [Optional]

It's possible to control how the folder structure for assets in Optimizely is done. By default, folders are created based on the year and month the asset was imported into Optimizely. Still, you could use other structures based on metadata in the solution. This is possible by implementing the IFolderResolver interface.

7. Customize Tiny MCE HTML template [Optional]

You have the possibility to implement your own input html when inserting in Tiny Mce, for example, filling the alt-text or adding some css classes.

This is done by implementing and registering an implementation of IFrontifyTinyMceTemplateResolver where you override GetHtml(ContentReference contentReference, string insertingToContentReference=null)

8. Event handling with Frontify events

The available events are:

  • OnImageDownloading: Raised before downloading an asset with the possibility to cancel the action.

  • OnImageDownloaded: Raised after the asset has been downloaded.

  • OnImageDeleted: Raised in the synchronization job when an asset is deleted or revoked in Frontify.

Here is an example of registering event handlers for these events in an InitializationModule:

public void Initialize(InitializationEngine context)
var events = context.Locate.Advanced.GetInstance<FrontifyEvents>();
events.OnImageDownloaded += FrontifyHttpClientOnImageDownloaded;
events.OnImageDownloading += EventsOnOnImageDownloading;
events.OnImageDeleted += FrontifyHttpClient_FrontifyImageDeleted;

10. Disabling the Frontify plugin in the Optimizely commerce asset list

Implement and register IFrontifyCommerceSettings.PreventCommerceEditorIntegration. By default, it's enabled.

11. Logging Frontify.Optimizely.Plugin

The addon has several logging data that can be used for information and debugging the integration. Update appsettings.json accordingly:

  "Logging": {
"LogLevel": {
"Frontify.Optimizely.Plugin": "Information"

12. Extras: Code samples

In the NuGet package, under tools, you'll find some code samples of IFolderResolver, IFrontifySettings, IFrontifyConfig, and IFrontifyTinyMceTemplateResolver implementations.

13. Multisite configuration

You can have different Frontify instances for different sites in Optimizely. Please implement the IFrontifyConfig interface.

Example: for each site:

public class ExampleFrontifySite1Config : IFrontifyConfig 
public IFrontifySettings Settings => new ExampleSiteOneFrontifySettings();//implement a contrate IFrontifySettings with all settings

public Guid SiteId => new Guid("b1c98de6-afbd-433c-bbde-97f873edbb12");//Change this from Optimizely / admin / config / websites

It will fall back to the default IFrontifySettings set globally if no SiteId is found.

14. How to use it in Frontend

The Frontify Image typically utilizes the CDN URL offered by the Frontify CDN as the default option. Still, the implementation may vary depending on personal preferences.

NOTE: Frontify CDN will not work with Optimizely TagHelpers.

For parameters asset processing Frontify CDN, check this link.

15. Authorization

To use Frontify in Optimizely with custom roles, you need to map your custom role to the "FrontifyUsers" role. Our API is authorized with [Authorize(Roles = "FrontifyUsers, WebEditors, WebAdmins")] by default.

Example implementations CSHTML

Alternate 1

@Html.PropertyFor(m => Model.CurrentPage.ImageAsContentReference)

Output: <img alt="aldo-delara-2AHdTdSj3U4-unsplash.jpg" src=""> (Image in full width)

Alternate 2

@Html.PropertyFor(m => Model.CurrentPage.ImageAsContentReference,
new { queryparameters = "format=webp&width=150", altAttr = "test with queryparameters"})

Alternate 3

<div data-epi-edit="ImageAsContentReference">
@Html.FrontifyCDN(Model.CurrentPage.ImageAsContentReference, new { width = 600, height = 300, format = "webp", quality = 100, crop="fp", fp="0.5,1", fp_zoom = 1.5, classAttr = "responsive", widthAttr = 600, heightAttr = 300, altAttr = "test" })

Alternate 4

<div @Html.EditAttributes(x => Model.CurrentPage.ImageAsContentReference)>
@Html.FrontifyCDN(Model.CurrentPage.ImageAsContentReference, new { width = 600, height = 300, format = "webp", quality = 100, crop="fp", fp="0.5,1", fp_zoom = 1.5, classAttr = "responsive test", widthAttr = 600, heightAttr = 300, altAttr = "test2" })

Alternate 5

@inject IContentLoader ContentLoader
ContentLoader.TryGet<IFrontifyMedia>(Model.CurrentPage.ImageAsContentReference, out IFrontifyMedia frontifyImage);

<div @Html.EditAttributes(x => Model.CurrentPage.ImageAsContentReference)>
<img src="@frontifyImage?.FrontifyUrl.FrontifyImage(new { width = 300, height = 300, format = "webp", quality = 75, crop="fp", fp="0.5,1", fp_zoom = 1.5 })" alt="@frontifyImage?.FrontifyAltText" class="custom" />

We hope you find this guide helpful; please contact us if you have any doubts. To get started with the Optimizely (v12) integration, please take a look at this help article.

Did this answer your question?