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

Summarize Graph results using facets

Facets in Optimizely Graph provide powerful aggregation and summarization capabilities for your content.

Facets are metadata or attributes attached to edges (relationships) between nodes. They add extra context about the connection, like timestamps, weights, roles, or labels, without needing a separate node. For example, in a "user > rated > movie" relationship, a facet could store the rating score or date of rating.

When summarizing graph results, facets let you aggregate or filter based on these edge attributes. For example, you can:

  • Summarize large datasets without retrieving all individual items
  • Create filtering interfaces with counts for each filter option
  • Analyze content distribution across different dimensions
  • Build dynamic navigation based on actual content

Facets enrich relationships with meaningful details, and they let you generate summaries or insights from graph queries by aggregating or filtering on those attributes.

Facet types

One of the biggest advantages of facets is that you can use them to summarize and analyze graph data. The following facet types are available in Optimizely Graph:

String facets

Use string facets to group and count items based on exact string values. This is useful for categorizing content and understanding the distribution of different categories.

The following query groups articles by their categories and counts the number of articles in each category:

query ArticlesByCategory($categoryFilters: [String!]) {
  ArticlePage {
    facets {
      Category {
        Name(filters: $categoryFilters) {
          name
          count
        }
      }
    }
    total
  }
}

The following are some example variables:

{
  "categoryFilters": ["Plan", "Meet", "Track"]
}

The following is the response for the example query:

{
  "data": {
    "ArticlePage": {
      "facets": {
        "Category": {
          "Name": [
            { "name": "Plan", "count": 2 },
            { "name": "Meet", "count": 1 },
            { "name": "Track", "count": 1 }
          ]
        }
      },
      "total": 4
    }
  }
}

Date facets

Use date facets to group content by specific date ranges. This is useful for tracking when content was published and analyzing trends over time.

The following query counts articles published on specific dates:

query ArticlesByPublishDate {
  ArticlePage {
    facets {
      StartPublish(unit: DAY) {
        name
        count
      }
    }
    total
  }
}

The following example response shows counts for articles published on each date:

{
  "data": {
    "ArticlePage": {
      "facets": {
        "StartPublish": [
          { "name": "2024-09-12", "count": 2 },
          { "name": "2024-09-11", "count": 1 },
          { "name": "2024-09-10", "count": 1 }
        ]
      },
      "total": 4
    }
  }
}

Numeric facets

Use numeric facets to group and count items based on numeric attributes. Although Price fields are unavailable in the Alloy template, you can use Status facets as an alternative.

The following query counts articles by their publication status, such as Published or Draft:

query ArticlesByStatus {
  ArticlePage {
    facets {
      Status {
        name
        count
      }
    }
    total
  }
}

The following is the response to the example query:

{
  "data": {
    "ArticlePage": {
      "facets": {
        "Status": [
          { "name": "Published", "count": 4 },
          { "name": "Draft", "count": 0 }
        ]
      },
      "total": 4
    }
  }
}

Combining facets with filters

Combining facets with filters lets you provide contextual summaries by narrowing down results to specific criteria.

The following query provides filtered results for specific categories, status breakdown, and publication timeline:

query TechnologyArticlesFacets($categories: [String!]) {
  ArticlePage {
    items {
      Name
      RelativePath
      Category {
        Name
      }
    }
    facets {
      # Get category distribution with filtering
      Category {
        Name(filters: $categories) {
          name
          count
        }
      }
      
      # Get status distribution within Plan category
      Status {
        name
        count
      }
      
      # Get publication date distribution
      StartPublish(unit: DAY) {
        name
        count
      }
    }
    total
  }
}

The following are some example variables:

{
  "categories": ["Plan", "Meet", "Track"]
}

Advanced faceting patterns

Multi-level facets

Multi-level facets create hierarchical summaries by organizing data into nested categories or levels.

The following query summarizes content by publication status across all content:

query ContentHierarchyFacets {
  Content {
    facets {
      # Publication status across all content
      Status {
        name
        count
      }
    }
    total
  }
}

Advanced facets like _typeName, Category on generic Content, and metadata fields are not available in the Alloy template schema. What is going on with "on generic" here?

Geographic facets

Use geographic facets to group and count items based on location attributes. Although event-based content types are not available, you can use available content types for location-based summaries.

The following query provides a summary of content by category and status:

query ContentByCategory {
  ArticlePage {
    facets {
      Category {
        Name {
          name
          count
        }
      }
      Status {
        name
        count
      }
    }
    total
  }
}

Time-based analysis

Time-based analysis tracks content trends over time, helping you understand patterns and changes in content publication. Multiple facets on the same field require aliases, and advanced time filtering is not available in the current schema.

The following query analyzes daily publication activity to track content trends over time:

query ContentTrends {
  ArticlePage {
    facets {
      # Daily publication activity
      startPublishDaily: StartPublish(unit: DAY) {
        name
        count
      }
    }
    total
  }
}

Build dynamic filter interfaces

Complete filter interface example

Building dynamic filter interfaces lets users interactively filter and explore content based on various criteria.

The following query builds a filter interface for articles based on category and publication date, letting users to explore content interactively:

query BuildFilterInterface($categoryFilter: String, $availableCategories: [String!]) {
  ArticlePage(
    where: {
      Category: { Name: { eq: $categoryFilter } }
    }
    limit: 20
  ) {
    items {
      Name
      RelativePath
      StartPublish
      Category {
        Name
      }
      TeaserText
    }
    
    facets {
      # Available categories (filtered to relevant options)
      Category {
        Name(filters: $availableCategories) {
          name
          count
        }
      }
      
      # Publication timeline
      StartPublish(unit: DAY) {
        name
        count
      }
      
      # Content status
      Status {
        name
        count
      }
    }
    
    total
  }
}

The following variables are available for filtered state:

{
  "categoryFilter": "Plan",
  "availableCategories": ["Plan", "Meet", "Track"]
}

The following variables are available for unfiltered state:

{
  "categoryFilter": null,
  "availableCategories": ["Plan", "Meet", "Track"]
}

Performance considerations

Facet optimization tips

  • Use simple facet queries – Focus on necessary facets to improve performance.
query OptimizedFacets {
  ArticlePage {
    facets {
      # Basic category facet
      Category {
        Name {
          name
          count
        }
      }
      
      # Status facet
      Status {
        name
        count
      }
    }
  }
}
  • Focus on available fields – Use fields that exist in your schema.
query WorkingFacets {
  ProductPage {
    facets {
      # Use fields that exist in the schema
      Category {
        Name {
          name
          count
        }
      }
    }
  }
}
  • Combine with WHERE clauses – Scope facets to relevant data.
query ScopedFacets {
  ArticlePage(
    where: {
      Status: { eq: "Published" }
    }
  ) {
    facets {
      # Facets only on published content
      Category {
        Name {
          name
          count
        }
      }
    }
  }
}

Real-world use cases

Content catalog with facets

Content catalogs with facets let users filter and explore a wide range of content efficiently.

The following query provides a content catalog with facets for filtering by search term and category:

query ContentCatalogWithFacets($searchTerm: String, $categoryFilter: String) {
  ProductPage(
    where: {
      _and: [
        { Name: { contains: $searchTerm } }
        { Category: { Name: { eq: $categoryFilter } } }
      ]
    }
    limit: 24
  ) {
    items {
      Name
      TeaserText
      PageImage {
        Url
      }
      Category {
        Name
      }
    }
    
    facets {
      Category {
        Name {
          name
          count
        }
      }
      
      Status {
        name
        count
      }
    }
    
    total
  }
}

Content dashboard analytics

Content dashboard analytics provide valuable insights into the distribution and status of content, enabling you to make informed decisions.

The following query provides content dashboard analytics by summarizing content status:

query ContentDashboard {
  Content {
    facets {
      # Content status distribution
      Status {
        name
        count
      }
    }
    total
  }
}

Advanced metadata facets like _typeName, _modified, and _createdBy are not available in the Alloy template schema.

Article timeline with facets

Article timeline facets let you track and analyze the publication timeline of articles.

The following query retrieves articles along with their publication dates, categories, and statuses, letting you analyze the timeline and distribution of content:

query ArticleTimelineFacets {
  ArticlePage {
    items {
      Name
      StartPublish
      RelativePath
      Category {
        Name
      }
    }
    
    facets {
      # Category distribution
      Category {
        Name {
          name
          count
        }
      }
      
      # Publication dates
      StartPublish(unit: DAY) {
        name
        count
      }
      
      # Status
      Status {
        name
        count
      }
    }
    
    total
  }
}

Best practices for facets

Optimizely recommends the following best practices when working with facets:

  • Use facets for summarization – Instead of retrieving all items, use facets to get counts when you only need summary information. This approach improves performance and efficiency.
  • Use the correct facet syntax – For complex fields, employ the nested structure. For example, use Category { Name { name count } } to ensure accurate data retrieval and representation.
  • Use the filters parameter – Limit facet results to relevant values by using filters. For example, Name(filters: $categories) lets you focus on specific categories, enhancing the relevance of your results.
  • Combine facets with filters – Provide contextual summaries by combining facets with filters. This practice lets you tailor results to specific queries or user needs.
  • Cache facet results – Facet results change less frequently than individual items. Cache them when possible to reduce server load and improve response times.
  • Use available fields – Stick to fields that exist in your schema, such as Category, Status, and StartPublish, to ensure compatibility and accuracy.

You should avoid making the following mistakes:

  • Do not assume all parameters are supported – The limit parameter is not available for facets, but filters is. Be mindful of the parameters you use to avoid errors.
  • Do not assume field availability – Fields like ArticleAuthor, Tags, Price, and Brand may not exist in your schema. Always verify field availability before using them.
  • Do not ignore empty facets – Handle cases where facets return no results gracefully. Implement logic to manage empty results to maintain a smooth user experience.
  • Do not use incorrect field names – Use name and count for facet results instead of Name and Count. Correct field names ensure accurate data retrieval and display.

Error handling for facets

Proper error handling ensures your application can handle cases where facets return no results.

The following query retrieves category facets filtered by specified categories. It helps ensure that even if no categories match the filters, the application can handle the situation without errors.

query FacetsWithErrorHandling($categoryFilters: [String!]) {
  ArticlePage {
    facets {
      # This might return empty if no categories exist
      Category {
        Name(filters: $categoryFilters) {
          name
          count
        }
      }
    }
    total
  }
}

The following JavaScript function processes the facet results and handles cases where the results might be empty:

function processFacetResults(facetData) {
  const categories = facetData?.Category?.Name || [];
  
  if (categories.length === 0) {
    console.log('No categories found');
    return [];
  }
  
  return categories.map(category => ({
    label: category.name,
    value: category.name,
    count: category.count
  }));
}