Skip to content

How a search page works ​

The search page from Getting started is a layout with a keyword field, a facet, a sort, the results, and a pager in it. This page follows one search through it: from the page the site renders, to the URL, to the endpoint, and back.

What the site renders ​

Drupal renders the layout as a search-root element and each block or component as one element inside it. The search page from Getting started comes out as this, with the layout's own wrapper markup left out:

html
<search-root url="/api/search/content" defaultPerPage="10" defaultResultDisplay="list">
  <search-input placeHolderText="Search" labelText="Search"></search-input>
  <search-sort type="select" labelText="Sort by"></search-sort>
  <search-result-summary></search-result-summary>
  <facet-checkbox key="content_type"></facet-checkbox>
  <search-results></search-results>
  <search-simple-pager></search-simple-pager>
  <search-no-results-message></search-no-results-message>
</search-root>

Each setting on the layout is an attribute on search-root: the endpoint URL, the default page size, the default listing layout, the announcements, and the filter dialog. Each setting on a block is an attribute on the component the block renders, e.g., the Search Input block's placeholder text. Drupal renders this markup once. Every search after that runs in the browser, against the endpoint.

The search root ​

The search root is the element responsible for talking to the endpoint. On load it reads the search from the page URL, sends it to the endpoint, and holds the response. Every component inside the root reads from the root. The results component reads the results, the facet reads its facet, and the pager reads the page count. When a visitor types a keyword, checks a facet option, or picks a page, that component asks the root to search again, and the root sends a new request. The root's response is the one source of truth on the page. No component fetches anything itself, and every component renders from the same response.

A search root comes from a Layout Builder section with a Search Components layout, a Canvas search layout component, or a search-root included in a Twig template. A component placed outside one does nothing: it has no root to ask and no response to read. The exception is Search Box, which sends the visitor to a search page from anywhere, e.g., a header.

Each search is written to the page URL. The second page of results for "cake" in recipes is:

/search?q=cake&f[content_type]=recipe&page=1
ParameterHolds
qThe keywords.
f[<alias>]A facet value, under the facet's URL alias. One parameter per value.
sort, orderThe sort option's alias, or a field and a direction. Left out for the default sort option.
limitThe page size. Left out for the default.
pageThe page, counted from 0. Left out for the first page.

Because the URL is the search, a bookmark or a shared link opens the same search, the browser's Back and Forward step through the searches, and a Search Box on another page can send a keyword by linking to /search?q=cake. For every parameter and how a sort is read, see URL state.

The root's updateUrl attribute decides whether the URL is written. In Layout Builder it is Update the page url with parameters from the search on the layout. In Canvas it is Do not update the page URL. With it off, the page also ignores search parameters in the URL it is opened with, so a Search Box cannot send keywords to it.

The request and the response ​

The root turns the search into a request to the endpoint from Getting started:

GET /api/search/content?q=cake&f[0]=content_type:recipe&page=1&limit=10

Drupal runs the search on the index and answers with JSON. The response holds the results of the page, the counts the pager and the summary need, the facets with their options and counts, and the endpoint's settings:

json
{
  "search_results": [{"id": "…", "title": "Victoria sponge cake", "url": "/recipes/victoria-sponge-cake", "type": "recipe", "rendered_item": "<article …>…</article>"}],
  "search_results_count": 12,
  "search_results_page": 1,
  "search_results_pages": 2,
  "search_results_per_page": 10,
  "facets": [{"key": "content_type", "label": "Content type", "active_values": ["recipe"], "results": [{"key": "recipe", "label": "recipe", "count": 12, "active": true}, {"key": "article", "label": "article", "count": 3, "active": false}]}],
  "swc_sorts": [{"label": "Relevance", "key": "search_api_relevance", "order": "desc", "alias": "relevance", "default": true}, {"label": "A-Z", "key": "title", "order": "asc", "alias": "title-asc"}],
  "swc_page_sizes": [{"key": "10", "label": "10"}, {"key": "25", "label": "25"}, {"key": "50", "label": "50"}],
  "swc_displays": [{"key": "list", "label": "List"}],
  "swc_results": {"field": "type", "mappings": [{"element": "search-result-element-rendered", "keys": ["default"], "settings": {"field": "rendered_item"}}]}
}

A result's fields are the index fields the endpoint sends. The swc_ keys are the settings from the endpoint's edit form, so the page offers the sort options, page sizes, and listing layouts set once on the endpoint. A block can override the list it shows with its own: Sort the sort options, Results per page the page sizes, Results display switcher the listing layouts, and Results the result elements. A facet's settings come from its widget, unless the block or component sets preferAttributes. For every key in the response, see The response. For every attribute a component takes, see its page in Storybook.

How a result is shown ​

The results component renders each result with a result element. The endpoint's Result elements rows decide which one. A row matches a result by the result's value in Match on field and by the listing layout the results are shown as. The endpoint from Getting started has one row, All values displayed with search-result-element-rendered, so every result is rendered by that element. It prints the HTML of the Rendered HTML output field, which is Drupal's own rendering of the content in a view mode, carried in the response. Indexing the rendered result explains why the HTML comes from the index. For a different result element per content type or listing layout, see Result elements.

Going further ​

  • Concepts: the context the root shares, the events of a search, and what the elements do before the first response.
  • Events: every event a page can listen to.
  • Searching another API: the request hooks that let the root search something other than a Search API Decoupled endpoint.
  • The two-column search page in Storybook, with a switch for each component.