Skip to main content
Documentation & User Guides | Fotoware

Optimizely Fotoware add-on (version 5.3) for Optimizely CMS 12 and .net 6

Learn how to install, configure, and use the Optimizely Fotoware add-on


This article explains how to install, configure, and use the Optimizely Fotoware add-on (version 5.0 or later). 

The export widget will work without Server API License but will not synchronize metadata; it will only download the image to Optimizely. 

See 16 Change Log.

Before you start

This article is technical and stipulates knowledge of the Optimizely ecosystem. We recommend getting assistance from someone experienced with Optimizely integrations to set up and configure the add-on.

Example Image Property and selection dialog from Fotoware


Example: TinyMce Toolbox button


How it works

When an asset is selected, the asset is imported into the default Optimizely asset management repository and used in an image property (of type ContentReference or Url) or the Rich Text editor. There is also an Optimizely scheduled job (to be enabled after installation), which ensures that the imported images and metadata are kept up to date in Optimizely if they change in Fotoware.

Key features of the integration:

  1. Easy to add to Optimizely solutions, both new and existing solutions.
  2. The integration can be removed without affecting used assets.
  3. Used assets from Fotoware are synchronized into Optimizely's default asset management, making it easy for developers familiar with Optimizely to get started.
  4. It is possible to configure media to show only local assets, only assets from Fotoware, or both.
  5. Developers can configure their own media models containing the metadata to be synchronized with Fotoware.
  6. Since downloaded media become standard Optimizely media items, Optimizely keeps track of which media is used where in the solution.

Note: Versions 1, 2, and 3 only support imports of static images such as .jpg files. PDFs may work but are not meant to. Video, .svg files, and animated gifs are not currently supported.


You can find information on (external link)

Installing and configuring the add-on takes less than one hour.


This version of the add-on requires at least EPiServer.CMS.UI 12.
The add-on automatically adds support for Optimizely Commerce and works on version 14 and higher.
Version 3 of EPiServer.CMS.TinyMce is needed for the Toolbox button in editor.

Registering the Selection Widget integration with Fotoware

Before setting up the Optimizely integration, you must register the application in the Fotoware Site Configuration. 

From the Tools menu (cogwheel icon), go to Site Configuration Integrations > Applications.

Select Add application to set up the integration for the Selection Widget.

Episerver Widget integration settings.jpg

Type: Select Web App / API and API (as in the example above).

Name: Enter the name of the application - for example Optimizely integration

Redirect URIs: Here, you set the URI that the user should be returned to after authentication is completed. The redirect URI is usually in the form:


Whether or not /episerver is part of the URI depends on how Optimizely has been configured. The redirect URI should be set in the Integrations settings above. Use small caps. In a multi-site scenario, one URI is needed per domain.

User consent: Use markdown syntax to add any custom information that should be displayed when the user uses the plugin for the first time. It's also possible to include a link to a privacy policy.

Access: This is used to control who has access to use the plugin.

Client ID / Client Secret: These values are auto-generated when you select Save (see the example below). Copy both values to a temporary location, such as a text file. Later, you must add these to the web.config file of the Optimizely plug-in, in Fotoware:ClientId and Fotoware:ClientSecret value fields (See web.config section below).
Once you have done this, you can delete the text file. If you lose the client secret, you can generate a new one and update the web.config file.


episerver widget client id and client secret.png


Registering the Server-to-Server integration 

Next, you must register a server-to-server authentication to complete the integration. This can be obtained in the Fotoware Site Configuration: Log in to your Fotoware tenant, open the Tools menu (cogwheel), and select Site configuration. The integration settings are found in the Integrations node, at Applications.

Add a new application and set the Type to Non-interactive/script, as seen in the screenshot below.

Episerver Server to server integration.jpg

Name the integration and select Save to generate the Client ID and Client secret values. Copy them to a working document and insert them in the Optimizely web.config file in the Fotoware:ServerApi:ClientId and Fotoware:ServerApi:ClientSecret value fields (see below).



1. Startup and appsettings.json:

Add services.AddFotowarePlugin(); into your startup.cs

public void ConfigureServices(IServiceCollection services)
        //at the end
"Fotoware": {
    <!-- all these data is to be obtained from Fotoware -->
    <!-- Documentation ClientId and Secret for Selection widget -->
    "ClientId": "[Enter your Fotoware guid]",
    "ClientSecret": "[Enter your client secret string]",
    <!-- Documentation for ServerApi ClientID and Secret -->
    "ServerApi": {
      "ClientId": "[Enter your Fotoware guid]",
      "ClientSecret": "[Enter your client secret string]"
    <!-- Leave RedirectUri empty or remove if nothing else is told to you. Domain is not required in Optimizely multisite solution, 
    or use default /episserver/fotoware.plugins.optimizely/authentication/callback
    where *episerver* is depending on your configuration. CASE SENSITIVE, use LOWER CASE  -->
    "RedirectUri": "/episerver/fotoware.plugins.optimizely/authentication/callback",
    "TenantUrl": "",
    <!-- which asset folder to import images to -->
    "RootFolderId": "[Enter an id to a media folder in Optimizely where you want downloaded assets, for instance 218]",
    <!-- presets is used to predefine a width of an image to download, can be used with Fotoware:PreferredDownloadWidth, presets are defined in Fotoware -->
    "PresetUrl": "/fotoweb/me/presets/export/[your presets guid]",
    <!-- these are optional -->
    <!-- EnableOnAllImages default is "true" -->
    /*"EnableOnAllImages": "false",*/
    /* ExportWidgetEnableOnAllImages default is "true" */
    /*"ExportWidgetEnableOnAllImages": "false",*/
    /* DisableEpiserverDefaultMediaSelector default is "false" */
    /*"DisableEpiserverDefaultMediaSelector": "true",*/
    "AllowedTypes": ".jpg,.jpeg,.jpe,.gif,.bmp,.png,.gif,.psd",
    /* PreferredDownloadWidth is important to be same or less than the presets width to work, zero is default and will den take the default presets width */
    "PreferredDownloadWidth": "1600",
    /*  Refresh token valid for days, then user need to login again, default is 14 */
    "RefreshToken": {
      "ValidDays": "1"
    /*"ArchiveUrlsToSynchronize": "/fotoware/archives/5000-Archive,/fotoware/archives/5000-Archive-2",*/  }

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

2. Configuring additional settings

You need to implement the IFotoWareMedia interface on a content type that inherits from Optimizely ImageData class in your solution. This will enable some additional fields that are used by the add-on to keep the assets in sync with the originals in Fotoware.

  [ContentType(GUID = "73738b8b-d6f1-4995-ba01-212c32eef6a5")]
  [MediaDescriptor(ExtensionString = "jpg,jpeg,jpe,ico,gif,bmp,png")]
public class ImageFile : ImageData,  IFotoWareMedia
    //Format: pipeseparated values. Example "internal fotoware href|download url|type of download url|site guid"
    public virtual string FotoWareUrl { get; set; } //Links back to Fotoware
    public virtual DateTime FotoWareModifiedDate { get; set; } //for sync job to work


(The FotoWareModifiedDate property is used to track when the asset was last changed in Fotoware. 

Note: An update to the metadata of an asset in Fotoware only adds 2 seconds to the modified date; therefore, we need to keep track of this date and time.

3. Add to your Tiny MCE configuration toolbar

The button is automatically plugged into Tiny MCE. If it doesn't show up, you probably already have a custom configuration. In startup.cs, add **fotoware-insert-media** to your toolbar.

4. Decorate your Optimizely Property with the Fotoware UIHint attribute:   

//FotoWareUiHint.FotoWareImage only for ContentReference type
public virtual ContentReference ImageAsContentReference { get; set; }
//FotoWareUiHint.FotoWareImageUrl only for Episerver.Url type
public virtual Url ImageAsUrl { get; set; }

This will replace Optimizely's built-in image editor with an extended editor that supports selecting images from Fotoware and local Optimizely images.

To disable the option to select local images in Optimizely, you can add another attribute to your property:

**FotowareConfigurationAttribute** is introduced in version 2. 
`[FotowareConfiguration(DisableDefaultEpiserverMedia = true, ExportWidgetEnabled = WidgetStatus.Disabled, /* only with XhtmlString, will use the export url from fotoware direct, instead of downloading the asset to Optimizely */ UseExportUrlOnly = false, QueryParameters = "crop=false&enhance=false&caption=false&action=false&publication=false&behaviour=false")]`

The attribute should be used in combination with FotoWareUiHint. The parameters are documented here Integrati...gets#section_7.

5. Scheduled jobs  

There are 2 jobs:

  • **Fotoware - Synchronize assets**:  Normally enabled if you want to sync updates from Fotoware to Optimizely. This job will only update assets if the assets have been updated in Fotoware.
  • **Fotoware - Synchronize assets - Force**: As above, but will always download the latest image and metadata. Only to be run manually if needed.


6. Synchronizing metadata from Fotoware to Optimizely

The add-on supports synchronizing metadata between Fotoware and Optimizely through a mapping schema defined in your implementation of the **IFotoWareSettings** interface. Implement your own **IFotoWareSettings** and define the mapping schema for metadata that you want to get into the Optimizely assets.
Note: There are some default metadata in Fotoware but these can be extended for each client. 

The default mapping schema is set up as follows:

MetadataConfiguration = new NameValueCollection
    {"5", "Name"},
    {"25", "Keywords"},
    {"80", "Photographers"},
    {"116", "Copyright"},
    {"120", "Description"}

The mapping schema has keys that match the metadata names in Fotoware and the value is the property name in Optimizely.
Note:  The types need to be the same when changing the configuration; for instance,  Photographers is a list of strings. 

You can find the default keys here: FotoWare_...MP_field_codes

The following example shows how to add custom metadata to the synchronization:

MetadataConfiguration = new NameValueCollection
    {"5", "Name"},
    {"25", "Keywords"},
    {"80", "Photographers"},
    {"116", "Copyright"},
    {"120", "Description"},
    {"998", "OptimizelyCustomProp"} // set on imagetype

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

Since Fotoware stores assets in a flat list and Optimizely uses a hierarchical structure, assets imported to Optimizely are placed in a folder structure. This helps when browsing the imported assets and avoids a long list of assets in the same folder, which Optimizely does not handle well. It is possible to manage how the folder structure for assets in Optimizely is structured. By default, folders are created based on the year and month the asset was imported into Optimizely, but you can use other structures, for instance, based on metadata in the solution.

This is done by implementing the **IFolderResolver** interface.

8. Customize Tiny MCE html template [Optional]

You can implement your own input HTML when inserting in Tiny Mce, for example, by filling the alt-text or adding some CSS classes. 

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

9. Event handling with Fotoware events

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 Fotoware.

The following example shows how to register event handlers for these events in an InitializationModule:

public void Initialize(InitializationEngine context)
   var events = context.Locate.Advanced.GetInstance<FotoWareEvents>();
   events.OnImageDownloaded += FotoWareHttpClientOnImageDownloaded;
   events.OnImageDownloading += EventsOnOnImageDownloading;
   events.OnImageDeleted += FotoWareHttpClient_FotoWareImageDeleted;

10. Disabling the Fotoware plugin in Optimizely Commerce Asset list

Implement and register IFotoWareCommerceSettings.PreventCommerceEditorIntegration.

By default, this is enabled.

11. Logging Fotoware.Plugins.Optimizely

The add-on has some logging information that can be used for information and debugging the integration. 

12. Extras: code samples

In the NuGet package under Tools, you can find some code samples of IFolderResolver, IFotoWareSettings, and IFotoWareTinyMceTemplateResolver implementations as well as additional scheduled jobs for synchronizing entire archives from Fotoware.

13. Troubleshooting

Tip: Turn on Logging Fotoware.Plugins.Optimizely.

14. Multi-site configuration

From version 3.5 and later, you can have different Fotoware instances for different sites in Optimizely.
You must implement the IFotoWareConfig interface. 

Example: For each site

   public class ExampleFotoWareSite1Config : IFotoWareConfig
        public IFotoWareSettings Settings => new ExampleSiteOneFotoWareSettings();//implement a concrete IFotoWareSettings with all settings
        public Guid SiteId => new Guid("b1c98de6-afbd-433c-bbde-97f873edbb12");//Get this guid from Episerver / admin / config / websites

It will revert to the default IFotoWareSettings set globally if siteid is not found.

15. Known issues

An error occurred when sending the request - This is probably due to the handshake with the endpoint not working. Make sure you use Tls12

Note: The callback URL is case-sensitive. Check your URL. Best practice is to use lowercase. 

16. Fotoware Optimizely/Episerver Plugin Change Log 

## - oct 2023

Add download API to svg, pdf, gif and png making it possible to download these extensions + transparent png + animated gifs

Newer Dojo Dialog window

Tested with EPiServer.CMS.TinyMce version 4.4.1 and Episerver.CMS 12.22.3

 "AllowedTypes": ".jpg,.jpeg,.jpe,.gif,.bmp,.png,.gif,.psd,.svg,.pdf"

New configs to disable Export Widgets:  "Fotoware:FilesNotOpenInExportApi": ".svg,.gif,.pdf", //default if not set => .png,.svg,.gif,.pdf


## - apr 2023

Compatibility with EPiServer.CMS.TinyMce version 4.1.

Update to the new thumbnail selector in Optimizely.
Fixed bug where environment appsettings were not used.

Added possibility to have IFotoWareMedia side by side with non-FotoWareMedia.

## - dec 2022

## - mar 2022 
Compatibility with .net 5 and Optimizely CMS 12 and Commerce 14
[Breaking change] From now on, the package name is Fotoware.Plugins.Optimizely (just change namespace everywhere)

## - jan 2022
#4734 [BUG] using widget import not working without export widget enabled

## - may 2021 
#3799 Use Export Url direct in WYSIWYG, without downloading the asset in Optimizely

## - apr 2021 
#3632 Multisite configuration - you can now have different Fotoware instances per site in Optimizely
#2985 Fotoware login token expiry (default 14 days)

## - mar 2021 
#3634 [BUG] Cookie is set as httpOnly from web.config <httpCookies httpOnlyCookies="true" requireSSL="true" />, javascript cant read, popup opens and closes several times

## - jan 2021 
[Breaking] Fotoware:ApiToken in appsetting is now removed and replaced with Fotoware:ServerApi:ClientId and Fotoware:ServerApi:ClientSecret.
#1749 Use Oauth server to server API authentication
#2926 You can now run the plugin with Export Widget without Server API License, then the asset is transferred but not the metadata. 

## - nov 06, 2020 (not public)
Last version with Fotoware:ApiToken configuration. Version 3 introduces Oauth server to server authentication
#392 [BUG] Image property is not updated in Optimizely. Change the window dialog popup against Optimizely javascript modal window. 
#2967 [BUG] Server error not showing if custom errorpage is enabled on server

## - june 07, 2020
#1800 [BUG] Images like PSD, are saved with psd in name, but should save as export format (jpg)
#1905 [Bug] Tinymce is always opening ExportWidget disregarding config
#1904 [BUG] TemplateResolver for TinyMce is not triggered

## - may 15, 2020
#1747 Accesstoken not fetched caused loop
#1748 Images with åäö not working
#844 cookie login user specific

## - jan 10, 2020
#391 Support for Export Widget
New - FotowareConfigurationAttribute

## - 2019-10-17
#388 Better logging and errormessages

## - 2019-10-07

#306 [Bug] Reloading existing synced images didn't allow publish
#307 [Bug] Drag n drop from windows didnt work on FotowareThumbnailSelector
#136 Enable Fotoware integration on all UIHint Image settings by default (config)
#137 Change download procedure to always download the latest assets if changed

## - 2019-09-18
#278 [BUG] Enable Custom Domains. Pagescripts validating domain against, this is removed

##initial release - 2019-06-01


  • Was this article helpful?