Reading time: 12 min read

How to create and manage custom sort options in Sitecore CEC

A complete walkthrough for defining global sorting criteria and updating widget variations to refine the user search experience.

Portrait photo of Gerald Encabo, article author

Customizing search discovery in Sitecore CEC

Sitecore's Customer Engagement Console (CEC) gives content teams direct control over how search results are ordered — without touching code. By configuring custom sort options in the CEC, you define the sorting strategies available to end users (e.g., "Most Recent", "Price: Low to High", or "Product Name: A to Z"), assign them to specific widgets, and control the order in which they appear in the UI.

This guide walks through the full lifecycle: from creating sort options in the CEC, to assigning them to widgets, to understanding how they surface in your front-end codebase.

Why custom sorting is key to search relevance

Default relevance-based sorting works well for general queries, but real-world search scenarios demand more tailored precision:

  • E-commerce - users expect to sort products by price, popularity, or newest arrivals.
  • Knowledge Bases - sorting by date ensures users find the most current documentation first.
  • Event Listings - chronological sorting (upcoming first) is essential for event discovery.
  • People Directories - alphabetical sorting provides a familiar browsing experience.

Custom sort options bridge the gap between what the search engine thinks is relevant and what the user actually needs. By tailoring sort choices per widget, you ensure each search experience matches its context — a product catalog shouldn't offer "Alphabetical by Last Name," and a people directory doesn't need "Price: Low to High."

Phase 1: Global configuration in domain settings

This phase creates reusable sorting options in your CEC domain. Think of it as building a library of sort strategies that can later be assigned to any widget.

1. Log in to the CEC and navigate to Administration > Domain Settings.

Fishtank blogging image

2. Under Feature Configuration, locate Sorting Options in the feature list and click the Edit icon to open its configuration screen. 

Fishtank blogging image

3. Click + Add Sorting Option and fill in the following:

  • Display Name - the user-facing label (e.g., Most Recent, File Name (Descending)).
  • API Name - the technical identifier referenced in your front-end code (e.g., m_mostrecent, name_desc). This value must match the defaultSortType used in your widget components.

Fishtank blogging image

4. Select a Sorting Type from the dropdown (Algorithm Sorting is selected by default). Each type has different configuration fields:

  • Option A - Algorithm Sorting
    • Set the direction to Ascending or Descending.

Fishtank blogging image

  • Option B - Attribute Sorting
    • Select an indexed Attribute (e.g., price, created_date).
    • Set the direction to Ascending or Descending.
    • (Optional) Set the analyzer to No analyzer or Lowercase. The analyzer options offered in the UI depend on the attribute you selected.

Fishtank blogging image

5. (Optional) To create a compound sort, click + Add Sorting Criteria to add additional criteria within the same sorting option. Results will be sorted by the first criterion, then by the second for ties, and so on. 

Fishtank blogging image

6. Click Save to add the sorting option to your global library.

Tip: Repeat steps 3 - 6 to add additional sorting options. Use the up/down arrows to re-order options in your global library. These options will be available for assignment to individual search widgets in Phase 2.

Algorithm vs. Attribute Sorting in CEC

Understanding the difference between the two sorting types is critical for choosing the right strategy:

  Algorithm Sorting Attribute Sorting
How it works Uses Sitecore Search's built-in ranking algorithm to score and rank results based on query context Sorts results by a specific indexed attribute value
CEC fields Direction only Attribute, Direction, Analyzer
Best for General search where relevance to the query matters most Structured data where users expect a predictable order
Examples "Most Relevant," "Featured" "Price: Low to High," "Most Recent," "File Name A - Z"
Direction Ascending / Descending (controls ranking interpretation) Ascending / Descending (literal field value ordering)
Requires No additional configuration — available by default An indexed attribute in your search schema (e.g., m_publisheddate, name)
Analyzer Not applicable Optional — defaults to No analyzer

Rule of thumb: Use algorithm sorting for open-ended search where query relevance should drive ranking; use attribute sorting when users need a fixed, predictable order (and ensure the attribute is indexed and populated). Compound criteria within one option are supported for tie-breaking.

Phase 2: Assigning sorting options to a widget

This phase connects the global sorting options (from Phase 1) to a specific widget, controlling which options appear in the UI and in what order.

1. Navigate to Widgets from the main CEC menu, then select the widget you want to configure (e.g., Product Search, Search Results or Category Page). 

Fishtank blogging image

2. Under Widget Variations, select the variation you wish to update, then locate and click the Edit icon on the variation. 

Fishtank blogging image

3. Select the rule you wish to update and click the Edit icon. In the rule editor, go to Settings > Sorting and configure the available options:

  • Enable the sorting options you want users to see for this widget.
  • Disable any options that are not relevant to this widget's context.

Fishtank blogging image

4. Arrange the enabled sorting options in the order they should appear in the UI. The first enabled option will be the default sort. 

Fishtank blogging image

5. Click Save to apply the changes to the variation.

6. Click Publish to push the configuration to the live search environment.

Before publishing: Review the enabled SORTING options list to confirm the selection and display order match your intended design. Publishing takes effect immediately on the live environment.

Fishtank blogging image

When to disable sort options

Not every widget needs every sort option. Disabling irrelevant options reduces clutter and improves the user experience. Here are common scenarios:

Scenario Action Reason
Product catalog widget Disable "File Name (Descending)" File name sorting is not meaningful for product discovery
People directory widget Disable "Most Recent" Users expect alphabetical order, not recency
Event listing widget Put a chronological sort first in the list (or disable Relevance) Users expect date order for events
Knowledge base widget Disable sorting options that depend on unpopulated attributes Prevents confusing results where all items appear in an arbitrary order
Single-purpose landing page Disable all but one option If there's only one meaningful sort, hide the dropdown entirely

Remember: when all sorting options are disabled for a widget, the sort dropdown will not render in the UI. The front-end code handles this automatically:

// widgets/SearchResults/components/SearchResultsToolbar/index.tsx
{totalItems > 0 && sortChoices.length > 0 && (
  <SortOptions options={sortChoices} selected={sortType} />
)}

Phase 3: Integration and code implementation

Once sorting options are configured in the CEC, they flow into your front-end automatically through the Sitecore Search SDK. The following sections show how the API exposes enabled choices (name / label), how the sort control renders them, and how selection can persist in the URL.

Here's what the end result looks like on a live product search page — the sort dropdown displays the Display Names configured in Phase 1, in the order set in Phase 2:

Fishtank blogging image

Now let's look at the code that makes this work.

1. Sort choices from the Search API

When the search widget loads, the useSearchResults hook fetches data from the Sitecore Search API. The response includes sort.choices — an array of the sorting options you enabled in Phase 2:

// widgets/SearchResults/ProductSearch/index.tsx
const {
  state: { sortType, page, itemsPerPage },
  queryResult: {
    data: {
      sort: { choices: sortChoices = [] } = {},
      content: productItems = [],
    } = {},
  },
} = useSearchResults<ProductModel, InitialState>({
  state: {
    sortType: defaultSortType,  // API Name from CEC (e.g., 'm_relevancy')
    page: defaultPage,
    itemsPerPage: defaultItemsPerPage,
    keyphrase: defaultKeyphrase,
    selectedFacets: [],
  },
});

The snippet above is simplified for readability. The full ProductSearch widget also passes a query callback (filters, sources, highlighting, and so on) and reads additional fields from the response.

Each item in sortChoices has two properties that map directly to CEC:

  • name - the API Name you entered in Phase 1
  • label - the Display Name you entered in Phase 1

2. The SortOrder component

The SortOrder component (default export from SortOrder/index.tsx) renders the sort dropdown that the end user interacts with. The toolbar typically imports that default export under a local name such as SortOptions (import SortOptions from '../SortOrder'). It uses @sitecore-search/ui primitives and calls onSortChange when the user selects a different option:

// widgets/SearchResults/components/SortOrder/index.tsx
import { useSearchResultsActions } from '@sitecore-search/react';
import { SortSelect } from '@sitecore-search/ui';
import { SortSelectStyled } from './styled';
const SortOrder = ({ options, selected }: SortOrderProps) => {
  const selectedSortIndex = options.findIndex((s) => s.name === selected);
  const { onSortChange } = useSearchResultsActions();
  return (
    <SortSelect.Root
      value={options[selectedSortIndex]?.name}
      onValueChange={onSortChange}
    >
      {/* Trigger button showing the selected option's Display Name */}
      <SortSelectStyled.Trigger>
        <SortSelectStyled.SelectValue>
          {selectedSortIndex > -1 ? options[selectedSortIndex].label : ''}
        </SortSelectStyled.SelectValue>
        <SortSelectStyled.Icon />
      </SortSelectStyled.Trigger>
      {/* Dropdown menu listing all enabled options from CEC */}
      <SortSelectStyled.Content>
        <SortSelectStyled.Viewport>
          {options.map((option) => (
            <SortSelectStyled.Option value={option} key={option.name}>
              <SortSelectStyled.OptionText>
                {option.label}
              </SortSelectStyled.OptionText>
            </SortSelectStyled.Option>
          ))}
        </SortSelectStyled.Viewport>
      </SortSelectStyled.Content>
    </SortSelect.Root>
  );
};

3. Conditional rendering in the toolbar

The SearchResultsToolbar conditionally renders the sort dropdown only when there are results and sort choices available. If you disable all sort options in the CEC for a widget, the dropdown disappears:

// widgets/SearchResults/components/SearchResultsToolbar/index.tsx
import SortOptions from '../SortOrder';
export const SearchResultsToolbar = ({ sortChoices, sortType, totalItems }) => {
  return (
    <div>
      {totalItems > 0 && sortChoices.length > 0 && (
        <SortOptions options={sortChoices} selected={sortType} />
      )}
    </div>
  );
};

The real toolbar also renders facets, result summaries, and responsive layout; only the sort conditional is shown here.

4. URL State persistence

The selected sort type is persisted in the URL hash, allowing users to share and bookmark sorted results. In this starter, the hash query parameter is sort (the CEC API Name); useSearchUrlState exposes it as sortType in your React code.

// lib/hooks/search/useSearchUrlState.ts
const { sortType, page, itemsPerPage } = useSearchUrlState({
  defaultSortType: 'm_relevancy',  // Fallback to API Name from CEC
  defaultPage: 1,
  defaultItemsPerPage: 10,
});

 

Key files reference

File Purpose
widgets/SearchResults/components/SortOrder/index.tsx Sort dropdown component
widgets/SearchResults/components/SortOrder/styled.ts Sort dropdown styling
widgets/SearchResults/components/SearchResultsToolbar/index.tsx Toolbar that conditionally renders the sort dropdown
widgets/SearchResults/ProductSearch/index.tsx Example widget consuming sort choices
lib/hooks/search/useSearchUrlState.ts URL state persistence for sort selection
lib/const/search-const.ts Shared search configuration and related constants (env, facets, some sort-related API names)

Validation and troubleshooting in the CEC

After publishing, verify that your sorting configuration works as expected.

Verification steps

  • Sort dropdown appears - confirm the sort dropdown renders on the target widget page. If it doesn't, check that at least one sort option is enabled in the CEC widget rule.
  • Correct options listed - verify that only the enabled options appear in the dropdown, in the order you configured.
  • Default sort is correct - the first enabled option should be pre-selected when the page loads. Confirm this matches your intended default.
  • Sort actually works - select each option and verify that results re-order correctly. Pay attention to attribute based sorts — if the underlying attribute isn't populated for all items, results may appear in an unexpected order.

Common issues

Symptom Likely Cause Fix
Sort dropdown doesn't appear No sort options enabled for this widget Enable at least one option in the CEC widget rule
Sort option appears but doesn't change results API Name mismatch between CEC and code Verify the defaultSortType in your widget matches the API Name in CEC
All results appear in the same order regardless of sort The sorted attribute is empty or unpopulated for most items Ensure the target attribute is indexed and populated in your content
New sort option not showing after publish Browser or CDN cache Clear browser cache or wait for CDN invalidation

Mastering the CEC lifecycle

Managing sort options is an ongoing process, not a one-time setup. Here's how to think about the full lifecycle:

Create → Assign → Validate → Iterate

  1. Create global sort options in Domain Settings (Phase 1) whenever a new sorting strategy is needed.
  2. Assign those options to the relevant widgets (Phase 2), choosing only the options that make sense for each context.
  3. Validate the configuration in preview and production (Validation section above).
  4. Iterate as content evolves, revisit your sort configuration. New content types may need new sort attributes. Underused options can be disabled to simplify the UI.

Best practices

  • Use consistent API names - follow a predictable pattern like m_relevancy, m_mostrecent, m_created_date_desc. This makes it easier for developers to reference them in code.
  • Keep Display Names user-friendly - use plain language like "Newest First" instead of technical names like "created_date descending".
  • Audit sort options quarterly - remove or disable options that analytics show are rarely used.
  • Document your sort options - maintain a shared reference of all API Names, their Display Names, and which widgets use them. This prevents drift between CEC configuration and code.
  • Test across locales - if your site supports multiple languages, verify that sort Display Names are appropriately localized in the CEC.

Bringing it all together

Custom sorting in Sitecore CEC is more than a configuration task — it's a continuous cycle of creating, assigning, validating, and iterating that directly shapes how users discover your content. This guide walked through that full lifecycle:

  1. Phase 1 - building a global library of sort options in Domain Settings, choosing between algorithm and attribute strategies.
  2. Phase 2 - assigning and ordering those options per widget, ensuring each search experience matches its context.
  3. Phase 3 - understanding how CEC configuration flows into front-end code through the Sitecore Search SDK, from sort.choices in the API response to the SortOrder dropdown in the UI.

References