> For the complete documentation index, see [llms.txt](https://docs.umbraco.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.umbraco.com/umbraco-cms/19.latest/develop-with-umbraco/search/extending-search/gathering-data-with-content-indexers.md).

# Gathering Data with Content Indexers

An explanation of the content indexer concept for search

When content changes, data is gathered for indexing using *content indexers*.

A content indexer is an implementation of `IContentIndexer`. There are two built-in content indexers:

* The [`SystemFieldsContentIndexer`](https://github.com/umbraco/Umbraco-CMS/blob/main/src/Umbraco.Cms.Search.Core/Services/ContentIndexing/Indexers/SystemFieldsContentIndexer.cs) gathers all [system fields](/umbraco-cms/19.latest/develop-with-umbraco/search/system-fields.md).
* The [`PropertyValueFieldsContentIndexer`](https://github.com/umbraco/Umbraco-CMS/blob/main/src/Umbraco.Cms.Search.Core/Services/ContentIndexing/Indexers/PropertyValueFieldsContentIndexer.cs) gathers all property values using the [property value handlers](/umbraco-cms/19.latest/develop-with-umbraco/search/extending-search/index-values-for-property-editors.md).

You can add additional content indexers if you need extra data indexed per content item.

## A custom content indexer

The following example appends extra index data for all content items being indexed. It uses a fictitious service, `IMyContentDataService`, to fetch the extra data on a per-item basis:

{% code title="MyContentIndexer.cs" %}

```csharp
using My.Site.Services;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Search.Indexing;

namespace My.Site.ContentIndexing;

public class MyContentIndexer : IContentIndexer
{
    private readonly IMyContentDataService _myContentDataService;

    public MyContentIndexer(IMyContentDataService myContentDataService)
        => _myContentDataService = myContentDataService;

    public async Task<IEnumerable<IndexField>> GetIndexFieldsAsync(
        IContentBase content,
        string?[] cultures,
        bool published,
        CancellationToken cancellationToken)
    {
        // Get the custom data for the content.
        IList<string> values = await _myContentDataService.GetSomeValuesAsync(content.Key);

        if (values.Count is 0)
        {
            // No custom data found, don't add anything to the index.
            return [];
        }
        
        // Add the custom data as searchable texts to a new index field called "myData".
        return [
            new IndexField(
                FieldName: "myData",
                Value: new IndexValue { Texts = values },
                Culture: null,
                Segment: null
            )
        ];
    }
}
```

{% endcode %}

{% hint style="info" %}
Content indexers are invoked for *all* types of content - documents, media and members.
{% endhint %}

You'll also need a composer to register the content indexer:

{% code title="MyContentIndexerComposer.cs" %}

```csharp
using My.Site.ContentIndexing;
using Umbraco.Cms.Core.Composing;
using Umbraco.Cms.Core.Search.Indexing;

namespace My.Site.DependencyInjection;

public class MyContentIndexerComposer : IComposer
{
    public void Compose(IUmbracoBuilder builder)
        => builder.Services.AddTransient<IContentIndexer, MyContentIndexer>();
}
```

{% endcode %}

## Content indexer outputs are cached

The index data produced by content indexers is cached in the Umbraco database to optimize index rebuilding.

First and foremost, this means that content indexers are *not* invoked during index rebuilds. This means you can use content indexers for expensive operations on a per-item basis.

Secondly, if your content indexer produces sensitive data, you need to pay extra attention. That data will also end in the cache. This might require you to take extra steps towards tracking sensitive data across your application.

You can read more about the index value cache and how to work with it in [the Database Cache for Index Values article](/umbraco-cms/19.latest/develop-with-umbraco/search/extending-search/database-cache-for-index-values.md).


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.umbraco.com/umbraco-cms/19.latest/develop-with-umbraco/search/extending-search/gathering-data-with-content-indexers.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
