Skip to content
Menu
Search
Browse documentation & this page

Developer Guide

Site search

Give your site a search page, change how results look, call search from a decoupled front end, and know what is searched, what is left out and what is recorded.

Cendia searches your published pages and gives you the results to print. The Starter ships a working search page at /search and a search box in the header.

The short version: there is nothing to set up. Publish a page and it can be found. The page that shows the results is yours to change.

The search page

Two files in your site:

File What it is
Pages/Search.cshtml The markup: the form, the list of results, the sort links, the pager. Change any of it.
Pages/Search.cshtml.cs One line. It derives from SiteSearchPageModel, which does the searching.
public sealed class SearchModel(ISiteSearch search) : SiteSearchPageModel(search) { }

In the template, Model.Results holds what was found:

Member What it holds
Results.Query What the visitor typed.
Results.Hits This page of results. Each has Title, Url, Summary, PublishedAt and ContentTypeId.
Results.Total, Results.Page, Results.TotalPages For the count and the pager.
Results.Offline True when an administrator has taken search offline.
Results.Featured, Results.FeaturedStyle Pages to show first, and how to dress them. See Featured results.
Results.Sort Relevance, Newest or Oldest.
Model.UrlFor(page, sort) A link to another page of the same search, or the same results in another order.
Model.ClickUrl Where the page reports that a result was opened. See What is recorded.

To show more or fewer results on a page, override PageSize in Search.cshtml.cs.

A result's Summary is plain text: the page's Meta Description when its author wrote one, otherwise the start of its text.

The query string

Parameter Meaning
q The words. Every word must match; the last may be the start of a word.
sort relevance (the default), newest or oldest.
page Which page of results, from 1.
lang A language code. Omitted, the language this host name serves by default.
sid Added by UrlFor. It marks a link as part of a search already made.

Moving the page

/search is a route in your site, not a page in the CMS. Change @page "/search" to move it, and update the action of the search form in _SiteLayout.cshtml to match.

Do not create a CMS page at the same address. Your route wins, so the CMS page would be unreachable, and nothing warns you.

An author can mark a page Featured on Settings > Search and give it phrases. A visitor whose search contains every word of one of those phrases is shown that page first, set apart from the other results. Cendia decides which pages those are; how the row looks is yours.

Model.Results.Featured holds them. They are only on the first page of results, are never repeated in Results.Hits, and are counted in Results.Total.

The row's markup

Pages/Shared/_FeaturedSearchResult.cshtml draws one featured result. Change it freely: add an image, a badge, a button. Its model is a SiteSearchHit:

Member What it holds
Title, Url The page's name and where to link.
Summary Its Meta Description, or the start of its text. Plain text.
PublishedAt, ContentTypeId When it was published, and its page type.
Id The page's id, for loading anything else about it, such as a picture.

Keep class="search__result-title" on the link. The search page reports a click on it, which the search reports depend on.

The row's style

An administrator sets five values on Settings > Designer > Featured Search. They reach your page as CSS custom properties in Results.FeaturedStyle, which Search.cshtml puts on the element wrapping the featured rows:

Property Set by
--search-featured-bg Background colour
--search-featured-title-size, --search-featured-title-color Title size and colour
--search-featured-text-size, --search-featured-text-color Description size and colour

A property is absent until somebody sets it, so give each a fallback in your stylesheet, as the Starter's site.css does:

.search__featured-result { background: var(--search-featured-bg, var(--paper-sunken)); }

If you do not want administrators changing the look, leave style="@results.FeaturedStyle" off the wrapper and style the row yourself.

  • The search contains every word of one of the page's phrases, as whole words, in any order.
  • The page passes everything under What is left out. Featuring ranks a page; it never includes one.
  • At most five lead one search, in name order.
  • Featured results come from Cendia whichever search provider you use.

From the API they are the featured array, beside items.

What is searched

  • Published pages only, in the language being searched. A draft is never searched.
  • A page's own text: its name, its Meta Title and Meta Description, and every text field its type declares.
  • The text of the blocks in its zones, including blocks inside those blocks. The result is always the page, because only a page has an address.

A match in the title counts most, then the Meta Description, then everything else. An administrator changes those weights on Settings > Configuration > Search, and a change applies to the next search: nothing is reindexed.

Keeping the index current

Publishing does it. A page going live rewrites its own entry, and a block going live rewrites the pages that show it. Nothing runs in the background to make a publish searchable.

The Search Reindex scheduled job rebuilds the whole index every twelve hours, as a net under that. It catches three things:

  • a block shown on more than 25 pages, such as a footer, whose publish leaves those pages to the job;
  • content changed in the database directly, not through the CMS;
  • a content type whose fields have changed since its pages were published.

Change how often it runs, or run it now, on Settings > Scheduled Jobs. Search keeps answering while it runs.

On Settings > Configuration > Search an administrator also has:

Control What it does
Clear Index Empties the index and starts a reindex from scratch. Search finds less than it should until the run finishes.
Take search offline Every search finds nothing and says so. Results.Offline is true, and the API returns "offline": true. Print "Search is offline", not "nothing found".
Preview Searches with the weights on the form, saved or not. Not recorded.

What is left out

A page is not a result when a visitor could not open it, or its author has said not to show it:

Left out Why
A page with Include in Search switched off Settings > Search on the page. For the whole page, or for one language.
A page whose publish date has not arrived, or that has expired It answers 404 or 410.
A page that redirects The link would not go where it says.
A page the visitor may not read Access rights. It is not counted either.
A page type with no template, such as a folder It has a URL that answers 404.
A block placed for some audiences only Most visitors never see that text.
A page on another website Each website searches its own pages.

All of these are checked when the search is made, not when the page was indexed. A page that expires at noon is out of search at noon.

Include in Search has nothing to do with search engines. That is the Robots field, in the same tab.

From a decoupled front end

GET /api/en-US/search?q=opera+tickets&sort=newest&page=1&size=10
{
  "culture": "en-US",
  "query": "opera tickets",
  "sort": "newest",
  "page": 1,
  "size": 10,
  "total": 14,
  "searchId": "3f6c0b1e-…",
  "items": [
    { "id": "…", "path": "/season/tickets", "title": "Tickets", "summary": "…",
      "type": "site.page.standardpage", "publishedAt": "2026-09-22T08:41:00+00:00" }
  ]
}
  • Pass searchId back as &searchId=… when you ask for another page of the same search, or the same results in another order, so it is not counted as a new search.
  • When your visitor opens a result, POST /api/search/{searchId}/click. It answers 204.
  • The API answers for a visitor who has not signed in, so only pages everybody may read are returned.

What is recorded

Every search is recorded for the search reports: the phrase, the website, the language, how many results it had, when, and whether a result was then opened. Nothing about who searched is recorded: no visitor id, no session, no address.

The click matters. A search with results where none was opened is how the reports tell a search that worked from one where nothing found was wanted. The Starter's page reports it for you, with the small script at the bottom of Search.cshtml. If you rewrite the page, keep data-search-click and that script, or report the click your own way.

The reports are under Reports > Site Search in the CMS: Most Frequent Searches, No Hits (a search that found nothing) and No Relevant Hits (a search that found results, none of which was opened). Each can be narrowed to a period, a website and a language. A fourth tab, Featured Search, lists every featured page with its phrases.

Searches are kept for three months. Change it in appsettings.json:

"Cendia": {
  "Search": { "Provider": "Internal", "LogRetentionMonths": 3 }
}

LogRetentionMonths is held between 1 and 18 whatever you set. The Search Log Retention scheduled job deletes what is older, once a day.

Using another search engine

Provider names what answers a search. Internal is Cendia's own index. A search provider package registers itself under its own name; set Provider to that name and your search page keeps working unchanged, because it only ever talks to ISiteSearch.

A provider replaces the search your visitors use. Searching inside the CMS always uses Cendia's own index.

To write one, implement ISiteSearchProvider and register it:

services.AddSingleton(new SiteSearchProviderRegistration(
    "MyEngine", sp => new MyEngineSearchProvider(/* … */)));

A request carries ExcludeItemIds: the featured pages already being shown. Leave them out of your results and your total, or a featured page appears twice.

Your provider must return only what the table above allows. An engine with an index of its own cannot check a visitor's access rights at search time, so send it only pages everybody may read.

Troubleshooting

What you see Likely cause
A published page is not found Include in Search is off for the page or the language, the page is restricted, or its type has no template. Check Settings > Search on the page.
A page is found by text it no longer shows The text is in a block shown on more than 25 pages, which waits for the reindex job. Run Search Reindex on Settings > Scheduled Jobs.
Every search says "Search is offline" An administrator ticked Take search offline on Settings > Configuration > Search.
Nothing is found on a site that had pages before upgrading The index is built once at startup, in the background. Give it a moment after the first start.
"Search provider 'X' is not registered" at startup Cendia:Search:Provider names a provider whose package is not installed. Set it to Internal.
/search answers 404 The page was deleted or moved. Check @page in Pages/Search.cshtml.