Disclaimer: This website requires Please enable JavaScript in your browser settings for the best experience.

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

Filter content

How to build efficient, filter-driven Optimizely Graph queries using best practices for structure, performance, and content targeting.

Optimizely Graph provides powerful filtering options based on the properties that exist in each content type.

How queries are structured

Optimizely Graph creates one type in the GraphQL API for each content type in CMS. You can configure fields in CMS such that they are filterable, searchable, or set to output only. You should configure fields that you do not need for filtering or searching to output for better performance only.

Field configuration types

  • Filterable – Use in where clauses for filtering.
  • Searchable – Use with text search operators like match and contains.
  • Output only – Use as read-only fields that you cannot filter or search (improves performance).

The following is a query example that filters articles by name and publish date:

query {
  ArticlePage(
    where: {
      # You must configure these fields as "filterable"
      Name: { eq: "Alloy Saves Bears" }
      StartPublish: { gte: "2024-01-01T00:00:00Z" }
    }
  ) {
    items {
      # These can be "output only" if you do not filter on them
      Name
      TeaserText
      MainBody
      StartPublish
    }
  }
}

Supported filter types and operators

Learn about the available Filter types and operators in Optimizely Graph.

Filter types

Equality filter – Filter based on exact matches. The following example filters articles by exact name:

query {
  ArticlePage(
    where: {
      Name: { eq: "Alloy Saves Bears" }
      # or: neq: "Excluded Article"
    }
  ) {
    items {
      Name
      TeaserText
    }
  }
}

Comparison filter – Filter based on comparisons like greater than or less than. The following example filters articles by a publish date range:

query {
  ArticlePage(
    where: {
      StartPublish: { 
        gte: "2024-01-01T00:00:00Z",  # Greater than or equal
        lte: "2024-12-31T23:59:59Z"   # Less than or equal
      }
    }
  ) {
    items {
      Name
      StartPublish
    }
  }
}

String filter – Filter based on string operations. Use the following query to find articles containing a specific word:

query {
  ArticlePage(
    where: {
      Name: { contains: "Alloy" }        # Contains substring
      # or: startsWith: "How to"         # Starts with
      # or: endsWith: "Guide"            # Ends with
      # or: match: "technology"          # Full-text match
    }
  ) {
    items {
      Name
      TeaserText
    }
  }
}

Array filter – Filter based on array values. The following query filters articles by categories:

query {
  ArticlePage(
    where: {
      Categories: { 
        in: ["Technology", "Innovation"]  # Match any value in array
      }
    }
  ) {
    items {
      Name
      Categories
    }
  }
}

Complex filter with AND/OR – Combine multiple conditions. The following example queries articles that you published on or after January 1, 2024, and whose name contains "Alloy" or whose teaser text contains "Technology":

query {
  ArticlePage(
    where: {
      _and: [
        { StartPublish: { gte: "2024-01-01T00:00:00Z" } },
        { 
          _or: [
            { Name: { contains: "Alloy" } },
            { TeaserText: { contains: "Technology" } }
          ]
        }
      ]
    }
  ) {
    items {
      Name
      TeaserText
      StartPublish
    }
  }
}

Reference type (CMS (SaaS) and CMS13)

Use the Reference type in CMS to reference content in other content types. The following query shows how to reference related content and categories:

query {
  ArticlePage {
    items {
      Name
      TeaserText
      # Reference to related content
      RelatedArticles {
        Name
        RelativePath
        TeaserText
      }
      # Reference to category
      Category {
        Name
        Description
      }
    }
  }
}

Query optimization best practices

Query for specific types

Queries should be small and contain as few types as possible. You should query for a concrete type, an abstract type, or an interface that contains the needed fields. The following example shows a specific query for articles:

# Good - Query specific content type
query GetArticles {
  ArticlePage(limit: 20) {
    items {
      Name
      TeaserText
      StartPublish
    }
  }
}

# Avoid - Generic query with many types
query GetAllContent {
  _Content {  # Too generic, poor performance
    items {
      ... on ArticlePage { Name TeaserText }
      ... on StandardPage { Name MainBody }
      ... on ProductPage { Name TeaserText }
      # ... many more fragments
    }
  }
}

Enable cached templates

Enable cached templates functionality in the queries to get improved results. From the CMS dashboard:

  1. Click GraphiQL.

  2. Click Stored Query to enable stored queries.

  3. Click Show Flags and enable stored templates.

In GraphQL requests,

  1. Add query-string parameter stored=true.
  2. Set the request header "cg-stored-query" to "template" (For example, cg-stored-query: template).

The following code shows how you can configure an HTTP client to use cached templates:

// HTTP client configuration for cached templates
const client = new ApolloClient({
  uri: 'https://cg.optimizely.com/content/v2?auth=YOUR_KEY&stored=true',
  headers: {
    'cg-stored-query': 'template'  // Enable cached templates
  }
});

Cached templates parameter support

Cached templates only work for the following parameter types:

  • Boolean
  • [Boolean]
  • Date
  • [Date]
  • DateTime
  • [DateTime]
  • String
  • [String]
  • Int
  • [Int]
  • Float
  • [Float]
  • Locales (variable name must be locale)
  • [Locales] (variable name must be locale)

The following is an example of using cached templates with supported parameter types:

# These parameter types work with cached templates
query CachedQuery(
  $searchTerm: String,          # String
  $tags: [String],              # [String]
  $isPublished: Boolean,        # Boolean
  $publishDate: DateTime,       # DateTime
  $limit: Int,                  # Int
  $locale: [Locales]            # [Locales] (must be named 'locale')
) {
  ArticlePage(
    where: {
      Name: { match: $searchTerm }
      Tags: { in: $tags }
      StartPublish: { gte: $publishDate }
    }
    limit: $limit
    locale: $locale
  ) {
    items {
      Name
      TeaserText
    }
  }
}

Avoid one query for all content types

You should not use one query for all content types. The following is an example of a better approach by using specific queries for each content type:

# Anti-pattern - One massive query for everything
query GetEverything($path: String!) {
  _Content(where: { RelativePath: { eq: $path } }) {
    items {
      ... on ArticlePage {
        Name TeaserText MainBody
      }
      ... on StandardPage {
        Name MainBody MetaTitle MetaDescription
      }
      ... on ProductPage {
        Name TeaserText MainBody
      }
      ... on LandingPage {
        Name HeroTitle HeroImage { Url }
      }
      # ... 20+ more content type fragments
    }
  }
}

# Better - Specific queries for each content type
query GetArticle($path: String!) {
  ArticlePage(where: { RelativePath: { eq: $path } }) {
    item {
      Name
      TeaserText
      MainBody
    }
  }
}

query GetStandardPage($path: String!) {
  StandardPage(where: { RelativePath: { eq: $path } }) {
    item {
      Name
      MainBody
      MetaTitle
    }
  }
}

Content type filter

The following query filters specific content types:

query GetSpecificContentTypes {
  Content(
    where: {
      _typeName: { in: ["ArticlePage", "LandingPage"] }
    }
  ) {
    items {
      Name
      RelativePath
      _typeName
    }
  }
}

Null or empty filters

Use the following query to filter articles with non-null teaser texts:

query GetArticlesWithTeasers {
  ArticlePage(
    where: {
      TeaserText: { neq: null }
    }
  ) {
    items {
      Name
      TeaserText
      RelativePath
    }
  }
}

Range filters

The following query retrieves recent articles based on the start publish date:

query GetRecentArticles {
  ArticlePage(
    where: {
      StartPublish: { 
        gte: "2024-01-01T00:00:00Z"
      }
    }
    orderBy: { StartPublish: DESC }
  ) {
    items {
      Name
      TeaserText
      StartPublish
      RelativePath
    }
  }
}

Practical filter examples

Filter by date range with variables

The following example shows how to filter articles by a date range using variables:

query GetArticlesByDateRange($startDate: DateTime!, $endDate: DateTime!) {
  ArticlePage(
    where: {
      StartPublish: {
        gte: $startDate,
        lte: $endDate
      }
    }
    orderBy: { StartPublish: DESC }
  ) {
    items {
      Name
      TeaserText
      StartPublish
      RelativePath
    }
  }
}

Variables:

{
  "startDate": "2024-01-01T00:00:00Z",
  "endDate": "2024-12-31T23:59:59Z"
}

Search and filter combined

The following example combines search and filtering by content type:

query SearchAndFilter($searchTerm: String!, $contentType: String!) {
  Content(
    where: {
      _and: [
        { _fulltext: { match: $searchTerm } },
        { _typeName: { eq: $contentType } }
      ]
    }
    orderBy: { _ranking: RELEVANCE }
  ) {
    items {
      Name
      RelativePath
      _typeName
      _score
    }
  }
}

Filter best practices

  1. Use specific content types (ArticlePage) instead of generic Content when possible.
  2. Combine filters with _and and _or for complex logic.
  3. Use variables for dynamic filtering.
  4. Index commonly filtered fields for better performance.
  5. Handle null values explicitly when needed.

Next steps

You now have the skills to filter content effectively. Enhance these abilities with related querying techniques. Begin with Sorting results to master ordering your filtered content, or explore Search functionality for powerful text-based content discovery.