Content Search

Search is often a multiple-step process: you take input from the user, perform the search and then display the results.

Let’s go through the basics first:

Then let’s dive a bit deeper:

Taking input from the user

There’s no one way that you have to stick to for outputting a search form.

Technically all you need is something like this:

<form method="get" action="/search">
    <label for="q">Search</label>
    <input id="q" name="q" type="search">
    <input value="Search" type="submit">

The easiest way to output such a form with Perch is to use perch_search_form(). Perch comes with a sample search templates/search/search-form.html which renders the form with Perch Form tags.

To perform a content search via Perch, you use perch_content_search().

A hard-coded example:

perch_content_search('opening hours');

If you’re using the default search form template, the form has method="get" which means the entered input will be available for you in the URL as query string parameter after you submit the form:


So you can get the query parameter from the URL to make the search take a dynamic value. You can use PHP’s $_GET, or for convenience you can you perch_get(), to get a query string parameter value:


If you are unfamiliar with perch_get(), you can refer to the function documentation or this blog post for more details.

Displaying the results

Perch comes with a sample template for displaying the search results templates/search/search-results.html. You can modify it, or specify your own:

perch_content_search(perch_get('q'), [
    'template' => 'my_template.html'

The template’s namespace is perch:search so all your template tags need to use this namespace regardless of the result source. So even if the result represents a blog post from the Blog app which uses the perch:blog namespace, you still need to display the search result with the perch:search namespace.

Result URL

Each result item includes a result_url value:

<perch:search id="result_url" />

How this value is determined varies depending on the source of the result. For instance, for multiple-item Regions and Collections you can define the item URL via the control panel in a dynamic way e.g. /services/{slug}. The Blog and Shop apps let you define the post and product URLs in the Settings.

The URL doesn’t have to be dynamic. If all the items share the same URL and are all displayed on the same page, it’s perfectly fine to use something like /services.

Using the add-trailing-slash option adds a trailing slash to result_url.

And if you’re using standard Perch, hide-default-doc hides the default document from result_url so that /services/index.php is output as /services.

perch_content_search(perch_get('q'), [
    'add-trailing-slash' => true,
    'hide-default-doc' => true,


The search results returned by perch_content_search() are paginated by default. You can control the number of items per page with the count option:

perch_content_search(perch_get('q'), [
    'count' => 12,

To disable pagination, set the count to null:

perch_content_search(perch_get('q'), [
    'count' => null,

What content is searched and what content is returned

Perch searches content via Search Handlers. A search handler is typically registered by an app.

Perch Content is a core app; you don’t have to install it, but technically it’s an app. It has its own search handler for searching content managed via Perch Content (Collections, Regions, Pages).

First-party apps also come with search handlers. So you can also use perch_content_search() to search Blog posts, Shop products, etc. If you are building a third-party app, you can register your own search handler.

The point is, it varies what content is searched based on the source of the content. For instance, if you add custom fields to your Blog post template post.html, they won’t be searchable. However, custom fields of Collection items are searchable. It depends on the app and how the search handler is set up.

It’s worth noting that the full-text search doesn’t work well with small quantity of content. A decent-sized data set is required for the search to return useful results.

As for what is returned, there are some common key data that is returned regardless of the result source such as the result URL, title, source and excerpt. Some search handlers may return more data. So it’s helpful to use perch:showall here to inspect what’s available to you.

Restricting the search to an app

perch_content_search() gives you the option to restrict the search results to an app or a number of apps.

perch_content_search(perch_get('q'), [
    'apps' => ['PerchShop', 'PerchBlog'],

Since Perch Content is also technically an app, you can also restrict the search results to Collections, Regions and Pages (i.e. items that are handled by Perch Content):

perch_content_search(perch_get('q'), [
    'apps' => ['PerchContent''],

Restricting the search to Collections

If you want the search results to only contain Collection items, you can specify PerchContent_RunwaySearch as an app. This won’t include Content Pages or Regions.

perch_content_search(perch_get('q'), [
    'apps' => ['PerchContent_RunwaySearch''],