---
title: Integrate Optimizely Search & Navigation with Optimizely CMS
slug: cms-12/docs/integrate-with-cms-1
docTags: 
createdAt: 2026-08-10T15:55:57.000Z
---

The extension includes specific components for using the Optimizely Search & Navigation .NET client API with the Optimizely Content Management System (CMS).

## Set up for development

The CMS extension assumes each environment has its own Search & Navigation index. It also assumes that content is added and removed through the CMS API. This means that:

- Each developer should have their development index unless you use a shared database.
- Each server environment (test, staging, and so on) should have its index unless it uses a shared database.
- If content is removed or added in ways other than the CMS API (for instance, using a database restore or rollback), you should run the scheduled job for re-indexing.

If you do not follow the previous guidelines, the search and querying functionality may appear to work but produce unexpected results. For example, the `GetContentResult` method returns less content than its `TotalMatching` property reports, which could happen if two developers use the same index, and one publishes a page that does not exist in the other developer's database.

## Packages

The following packages are used for Search & Navigation-specific integrations:

- `Episerver.Find.Cms` – Integration of Find REST API with Optimizely Content Management System (CMS).
- `EPiServer.Find` – The .NET client API for the Find REST API (installed with `EPiServer.Find.Cms`).
- `EPiServer.Find.Framework` – General integration components for the Find REST API (installed with `EPiServer.Find.Cms`).
- `EPiServer.Find.Cms.AttachmentFilter` – File type parser for CMS attachments.
- `EPiServer.Commerce.FindSearchProvider` – Integration components for [Optimizely Commerce Connect (v13)](docId\:kYhZA63a_WhiL3MB8PeaG).
- `EPiServer.Find.Commerce` – Integration components for [Optimizely Commerce Connect (v13)](docId\:kYhZA63a_WhiL3MB8PeaG).
- `EPiServer.Find.Personalization` – Integration components for Personalized Search & Navigation.

Reference the assemblies needed in your project, and add the [standard configuration for the .NET API to web.config](docId:7DPNSuEGiCUQ8fvjuRqZl).

:::hint{type="info"}
**Note**
If you installed Optimizely Search & Navigation with a sample site through the Visual Studio extensions, the integration with CMS is automatically set up.
:::

## Extension components

The Optimizely Search & Navigation extension builds on a .NET-based client API, adding functionality for automatically indexing objects and methods for filtering, retrieving, and caching results. The following list shows some of the functionality you get with the extension:

- `IndexingModule` – Hooks up events to handle content indexing (`IContent` objects).
- `SearchClient.Instance` – To manage the `SearchClient.Instance` object, conventions are applied to exclude certain properties of the `IContent` object and other CMS classes while also incorporating additional fields. This process is executed by the `IndexingModule` during startup through the `CmsClientConventions` class. When using the general .NET API, you typically create an `IClient` instance with the `Client.CreateFromConfig` method. In alignment with the standard development approach, the Optimizely integration offers a singleton instance via the `SearchClient` class and its `Instance` property. Although the instance returned is a standard `IClient`, it undergoes some modifications at startup. Therefore, when working with CMS and Search & Navigation, it is important to use `SearchClient.Instance`.

:::hint{type="danger"}
**Warning**
Differences between the authentication mechanism of `EPiServer.ServiceAPI` and `EPiServer.Find` may lead to the incorrect functioning of user authentication. To avoid these problems, you should install `EPiServer.ServiceAPI` in a separate application.
:::

- `ContentIndexer` – This class handles the indexing, re-indexing, and removing content from the index. You can customize content to be indexed by modifying its conventions.
- `GetContentResult` – Call this extension method to execute search requests and get actual `IContent` objects back.
- **Episerver Find (Search & Navigation) Content Indexing Job** – A scheduled job that handles content re-indexing.
- Several additional filter methods, such as `ContentReference`, make it more convenient to filter on CMS types.

## Content Security Policy update for Service Health dashboard

To ensure the Service Health view in the Optimizely Search & Navigation UI functions correctly, clients must update their Content Security Policy (CSP) settings. If you have implemented a CSP, then it is likely in your `Startup.cs` it might look something like this:

```csharp
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
  if (env.IsDevelopment()) {
    app.UseDeveloperExceptionPage();
    app.UseMiddleware < AdministratorRegistrationPageMiddleware > ();
  }

  // Add Content Security Policy (CSP)
  app.Use(async (context, next) => {
    context.Response.Headers.Add(
      "Content-Security-Policy",
      "default-src 'self'; " +
      "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.optimizely.com; " +
      "img-src 'self' data: https://*.optimizely.com; " +
      "style-src 'self' 'unsafe-inline' https://localhost:44333; " +
      "font-src 'self' https://*.cloudfront.net https://localhost:44333; " +
      "connect-src 'self' ws://localhost:* http://localhost:*;" +
      "object-src 'none';"
    );
    await next.Invoke();
  });

  app.UseStaticFiles();
  app.UseRouting();
  app.UseAuthentication();
  app.UseAuthorization();
  app.UseEndpoints(endpoints => {
    endpoints.MapContent();
    endpoints.MapControllerRoute("Register", "/Register", new {
      controller = "Register", action = "Index"
    });
    endpoints.MapControllerRoute(
      name: "default",
      pattern: "{controller=Home}/{action=Index}/{id?}");
    endpoints.MapRazorPages();
  });
}
```

To fix it and let the Service Health Dashboard function correctly, add the following directive to the CSP header configuration:

```csharp
"frame-src 'self' dashboard.find.episerver.net;" +
```

The updated CSP configuration should look like this:

```csharp
app.Use(async (context, next) => {
  context.Response.Headers.Add(
    "Content-Security-Policy",
    "default-src 'self'; " +
    "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdn.optimizely.com; " +
    "img-src 'self' data: https://*.optimizely.com; " +
    "style-src 'self' 'unsafe-inline' https://localhost:44333; " +
    "font-src 'self' https://*.cloudfront.net https://localhost:44333; " +
    "connect-src 'self' ws://localhost:* http://localhost:*;" +
    "frame-src 'self' dashboard.find.episerver.net;" + // Added directive
    "object-src 'none';"
  );
  await next.Invoke();
});
```

Updating your CSP settings as shown lets the necessary connections for the Service Health view operate properly.
