Dev guideRecipesAPI ReferenceChangelog
Dev guideRecipesUser GuidesNuGetDev CommunityOptimizely AcademySubmit a ticketLog In
Dev guide

Migrate best bets to pinned results

Migrate Optimizely Search & Navigation best bets to Optimizely Graph pinned results, covers configuration differences, data mapping, API usage, and search query updates.

Best bets in Optimizely Search & Navigation and pinned results in Optimizely Graph let you promote specific content to the top of search results for defined search phrases. This ensures that users see important or authoritative content before other results.

This guide explains how to migrate existing best bets configurations from Optimizely Search & Navigation to Optimizely Graph pinned results, including API usage, data mapping, and query updates.

When to use pinned results

  • Promote branded or navigational searches. For example, directing users to an About us page for company-related queries.
  • Highlight campaign or seasonal content for specific keywords.
  • Ensure critical support or contact information appears first in search results.
  • Guide users to official or compliant content for regulatory or policy-related searches.

Key differences and migration impact

The following table summarizes the main differences between Search & Navigation best bets and Optimizely Graph pinned results and highlights required migration actions.

FeatureSearch & NavigationGraphMigration impact
ConfigurationAdmin UIREST API onlyBuild an API-based integration (HMAC or Basic authentication required)
ArchitecturePhrase-to-content mappingCollection-basedCreate collections, then add pinned items
Content referenceInteger IDGUIDQuery Graph to map ContentReference.ID to ContentReference.GuidValue
Supported contentInternal and external URLsInternal content onlyMigrate internal content; handle external URLs separately
Title and descriptionCustom or derived from contentNot supportedUse content fields in the application layer
Display stylingConfigurable in UINot supportedImplement styling in the application layer
Language handlingSingle item can apply to all languagesSeparate item per languageCreate one pinned item per language
Priority controlImplicit (insertion order)Explicit priority fieldAssign priorities sequentially (1 is highest)
Result limitUnlimitedMaximum of 5Select the five most important results
Query syntax.ApplyBestBets()pinned parameterUpdate all search queries
Locale handlingAutomaticExplicitAlways specify locale in queries
StatusDelete to removeActive or inactiveUse status for temporary or seasonal items
📘

Note

Both Optimizely Search & Navigation and Optimizely Graph support case-insensitive phrase matching.

Migration workflow

Retrieve best bets from Search & Navigation

Use the IBestBetRepository interface to retrieve existing best bets. You must have the following prerequisites:

  • EPiServer.Find.Framework
  • EPiServer.Find.Cms
  • Optimizely.ContentGraph.Core
using EPiServer.Find;
using EPiServer.Find.Framework.BestBets;
using EPiServer.Find.Cms;


var allBestBets = _bestBetRepository.List().ToList();


var internalBestBets = allBestBets
.Where(bb => bb.BestBetSelector is PageBestBetSelector)
.ToList();
📘

Note

Optimizely Graph supports internal CMS content only. You cannot migrate best bets that reference external URLs, you must handle them separately.

Map content ID to Graph GUID

Optimizely Graph uses content GUIDs instead of integer content IDs. Query Graph to retrieve GUID values for the content you plan to pin.

query GetContentIds($ids: [Int!]) {
	Content(where: { ContentLink: { Id: { in: $ids } } }, limit: 100) {
		items {
			ContentLink {
				Id
				GuidValue
			}
		}
	}
}

Store the mapping between ContentReference.ID and ContentReference.GuidValue for later use.

Create a pinned results collection

Create a collection to group related pinned results using the following endpoint:

POST https://cg.optimizely.com/api/pinned/collections
{
  "title": "Migrated Best Bets",
  "key": "COLLECTION_GUID",
  "isActive": true
}

Save the collection key for use in GraphQL queries.

Add pinned items to the collection

Add each migrated best bet as a pinned item using the following endpoint:

POST https://cg.optimizely.com/api/pinned/collections/{id}/items
{
  "phrases": "support",
  "targetKey": "<CONTENT_GUID>",
  "language": "en",
  "priority": 1
}

Update application search queries

Replace Search & Navigation-based search queries with Graph queries that use the pinned parameter.

query SearchWithPinnedResults(
  $term: String!
  $collection: String!
  $locale: [Locales!]
) {
  Content(
    where: { _fulltext: { contains: $term } }
    pinned: { phrase: $term, collections: [$collection] }
    locale: $locale
  ) {
    items {
      Name
      Url
    }
  }
}

Pinned results appear first in the response, followed by regular search results.

Verify and test

Verify collections and pinned items using the REST API or Swagger UI, then validate search behavior using GraphiQL.

Remove the pinned parameter to compare results with and without pinned content.

Verify with REST API

Use the Swagger UI or direct API calls to verify your migration.

Use the following endpoint to get all collections:

GET https://cg.optimizely.com/api/pinned/collections
// Requires HMAC or Basic Auth

The following is an example response to get all collections:

[
  {
    "id": "COLLECTION GUID",
    "title": "Migrated Best Bets",
    "key": "migrated-best-bets",
    "isActive": true
  }
]

Use the following endpoint to get items in a collection:

GET https://cg.optimizely.com/api/pinned/collections/{id}/items
// Requires HMAC or Basic Auth

The following is an example response to get items in a collection:

[
  {
    "id": "ITEM_GUID",
    "phrases": "support",
    "targetKey": "12345678-abcd-1234-abcd-1234567890ab",
    "language": "en",
    "priority": 1,
    "isActive": true
  }
]

Test with GraphQL

Test using GraphiQL: https://cg.optimizely.com/app/graphiql?auth=YOUR_SINGLE_KEY.

For example:

query {
  Content(
    where: { _fulltext: { contains: "support" } }
    pinned: {
      phrase: "support"
      collections: ["migrated-best-bets"]        # Use collection key, not ID
      # collections: ["water", "chemistry"]      # Multiple collections supported
    }
    locale: en
  ) {
    items { Name Url }
  }
}