---
title: Migrate synonyms
slug: graph/docs/migrate-synonyms
docTags: 
createdAt: 2026-07-30T20:30:19.772Z
---

Migrate synonym functionality from Optimizely Search & Navigation to Optimizely Graph. This article explains differences in configuration, language handling, query behavior, and operator support. It also provides migration approaches for both small and large synonym sets. Use the information to preserve synonym behavior while running Search & Navigation and Graph in parallel during migration.

Synonyms expand search queries with equivalent or related terms. They improve search relevance and reduce zero-result searches when users use different terminology.

Use synonyms when:

- Users search for different terms for the same concept (for example, *bike* and *bicycle*).
- Brand names have common alternatives (for example, *mib* and *men in black*).
- Technical terms have widely used alternatives (for example, *H2O* and *water*).

Learn more about [feature comparisons](docId\:sNcLLcLYgWv_QVb0Mtqus) for synonyms.

## Migration options

Choose to do a manual migration or a programmatic migration.

- Manual migration – Recommended for small to medium-sized synonym lists. Uses Search & Navigation Admin UI export and manual conversion.
- Programmatic migration – Recommended for large synonym lists or multiple languages. Automates the entire migration process using code.

## Manual migration

Manual migration is recommended for small to medium-sized synonym lists. It uses the Search & Navigation Admin UI export and manual conversion.

### Export synonyms from Search & Navigation Admin UI

1. Go to **Menu** > **Search & Navigation**.
2. Go to **Optimize** > **Synonyms**.
3. Click **Export**.
4. Save the CSV file.

### Convert to Graph plain text format

The following conversion rules apply:

- **Bidirectional** (Search & Navigation: `bidirectional: true`) – Use commas.
- **One-way** (Search & Navigation: `bidirectional: false`) – Use the `=>` arrow.

The following is an example conversion from Search & Navigation CSV export:

```csv
phrase,bidirectional,synonym
"bike",true,"bicycle"
"h2o",true,"water"
"mib",false,"men in black"
```

The following is an example conversion to Graph plain text:

```javascript
bike, bicycle
h2o, water
mib => men in black
```

### Upload to Graph via the API

Complete the following steps using Postman or Swagger UI:

1. Go to [https://cg.optimizely.com/app/swagger](https://cg.optimizely.com/app/swagger).
2. Locate the `PUT /resources/synonyms` endpoint.
3. Set `language_routing` and `synonym_slot` parameters accordingly.
4. Set body (raw text):

```text
bike, bicycle
h2o, water
mib => men in black
```

5. Click **Execute**.

:::hint{type="warning"}
**Important**
For **All languages** synonyms from Search & Navigation, repeat steps 1 through 5 for each language your application supports. For example, `language_routing=en`, then `language_routing=sv`, then `language_routing=fr`, and so on.
:::

## Programmatic migration

Programmatic migration is recommended for large synonym lists or multiple languages. It automates the entire migration process using code.

### Fetch synonyms from Search & Navigation

For a specific language:

```csharp
var languageCode = Language.English.FieldSuffix; // e.g., "en"
var client = SearchClient.Instance;
var allSynonyms = client.Optimizations().Synonyms().List(size: 100, from: 0, [$"language:{languageCode}"]);
```

For **All languages** synonyms:

```csharp
// Note: Language.All.FieldSuffix returns a GUID, not a language code
var allLanguagesCode = Language.All.FieldSuffix;
var client = SearchClient.Instance;
var allLanguagesSynonyms = client.Optimizations().Synonyms().List(size: 100, from: 0, [$"language:{allLanguagesCode}"]);
```

:::hint{type="warning"}
**Important**
If you have **All languages** synonyms in Optimizely Search & Navigation, you must upload them to each individual language in Graph.
:::

### Convert to Graph plain text format

```csharp
var graphSynonyms = new StringBuilder();
foreach (var synonym in allSynonyms.Hits)
{
    var formattedSynonym = synonym.Bidirectional
        ? $"{synonym.Phrase}, {synonym.SynonymPhrase}"
        : $"{synonym.Phrase} => {synonym.SynonymPhrase}";
    graphSynonyms.AppendLine(formattedSynonym);
}
string plainTextContent = graphSynonyms.ToString().TrimEnd();
```

### Upload to Graph with HTTP client

:::hint{type="info"}
**Note**
This example uses basic authentication. For better security, use [HMAC authentication](docId\:sNcLLcLYgWv_QVb0Mtqus) instead.
:::

```csharp
// Configure Basic authentication credentials
var appKey = "YOUR-APP-KEY";
var secret = "YOUR-APP-SECRET";
var credentials = Convert.ToBase64String(
    Encoding.UTF8.GetBytes($"{appKey}:{secret}")
);

// Upload to Graph
var httpClient = new HttpClient();
var graphLanguageCode = "en";
var synonymSlot = "one";
var url = $"https://cg.optimizely.com/resources/synonyms?language_routing={graphLanguageCode}&synonym_slot={synonymSlot}";

var request = new HttpRequestMessage(HttpMethod.Put, url);
request.Headers.Add("Authorization", $"Basic {credentials}");
request.Content = new StringContent(plainTextContent, Encoding.UTF8, "text/plain");

var response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode();
```

## Update application queries after migration

After migrating synonyms to Graph, update your application code to use GraphQL queries with synonym support.

The following is an example of Search & Navigation before migration:

```csharp
var results = await SearchClient.Instance
    .Search<IContent>(Language.English)
    .For("bicycle")
    .InField(x => x.Name)
    .UsingSynonyms()
    .Take(10)
    .GetContentResultAsync();
```

The following is an example of Graph after executing GraphQL queries in C#:

```csharp
using Optimizely.ContentGraph.Core;

public class SearchService
{
    private readonly IClient _graphClient;

    public SearchService(IClient graphClient)
    {
        _graphClient = graphClient;
    }

    public async Task<SearchResult> SearchWithSynonymsAsync(string searchTerm)
    {
        var query = @"
            query SearchContent($searchTerm: String!) {
              Content(
                where: { Name: { contains: $searchTerm, synonyms: [ONE] } }
                locale: en
                limit: 10
              ) {
                total
                items {
                  Name
                  ContentType
                }
              }
            }";

        var variables = new { searchTerm };
        var result = await _graphClient.QueryAsync(query, variables);
        return result;
    }
}
```

## Verify and test

After uploading synonyms, verify the upload was successful and test synonym functionality.

### Verify upload with REST API

Confirm the upload succeeded using the Swagger UI.

1. Go to [https://cg.optimizely.com/app/swagger](https://cg.optimizely.com/app/swagger).
2. Locate the `GET /resources/synonyms` endpoint.
3. Set `language_routing` and `synonym_slot` parameters accordingly.
4. Execute the request.
5. Verify the response contains your synonym list.

### Test synonyms with Optimizely GraphQL

Test synonym expansion using GraphiQL: [https://cg.optimizely.com/app/graphiql?auth=YOUR\_SINGLE\_KEY](https://cg.optimizely.com/app/graphiql?auth=YOUR_SINGLE_KEY).

The following is an example of testing bidirectional synonyms:

```graphql
# Searching for "bike" should find content with both "bike" and "bicycle"
{
  Content(where: { Name: { contains: "bike", synonyms: [ONE] } }) {
    total
    items {
      Name
    }
  }
}
```

The following is an example of testing one-way synonyms:

```graphql
# Searching for "mib" should find "men in black"
{
  Content(where: { _fulltext: { contains: "mib", synonyms: [ONE] } }) {
    total
    items {
      Name
      _fulltext
    }
  }
}
```

The following example tests both synonym slots:

```graphql
{
  Content(where: { Name: { contains: "laptop", synonyms: [ONE, TWO] } }) {
    total
    items {
      Name
    }
  }
}
```

For more query examples, see [Query with synonyms](docId\:sNcLLcLYgWv_QVb0Mtqus).
