Skip to content

Finding Entries That Use Specific Matrix Blocks in Craft CMS

With a simple Twig template, you can get every entry that contains a specific block type. Perfect for content audits or before making big changes to Matrix fields.

If you’ve worked with Craft CMS for any length of time, you know that Matrix is probably the killer field type. And it’s likely that you’ve needed to update or remove a particular block, but first you want to know which entries are actually using it.

Perhaps you’re deprecating an old content block, troubleshooting an issue, or just doing a content audit. Whatever the reason may be, Craft doesn’t provide a simple built-in way to search for entries by the specific Matrix blocks they contain. The search index covers the content within the blocks, but not the block types themselves.

Fortunately, with a bit of Twig, you can create your own search tool that does exactly this. And this technique works for both Craft 4 and 5.

The Twig Code

Here's the Twig code that will find all entries using a specific Matrix block type:

{% set entriesWithBlock = craft.entries()
    .myMatrixFieldHandle(':notempty:')
    .all() %}

{% set filteredEntries = [] %}
{% for entry in entriesWithBlock %}
    {% for block in entry.myMatrixFieldHandle.all() %}
        {% if block.type.handle == 'formEmbedBlock' %}
            {% set filteredEntries = filteredEntries|merge([entry]) %}
        {% endif %}
    {% endfor %}
{% endfor %}

{# Output the results #}
{% for entry in filteredEntries|unique %}
    <p>{{ entry.title }} ({{ entry.url }})</p>
{% endfor %}

Let’s break this down.

Step 1: Get all entries with content in your Matrix field

{% set entriesWithBlock = craft.entries()
    .myMatrixFieldHandle(':notempty:')
    .all() %}

This first bit of code queries for all entries where your Matrix field is not empty. The :notempty parameter helps narrow things down from the start so that you’re not checking entries that definitely don’t have any Matrix blocks.

(Don’t forget to replace myMatrixFieldHandle with your actual Matrix field handle.)

Step 2: Loop through entries and their blocks

{% for entry in entriesWithBlock %}
    {% for block in entry.myMatrixFieldHandle.all() %}

Here we loop through all of the Matrix blocks in each entry.

Step 3: Check for your specific block type

{% if block.type.handle == 'formEmbedBlock' %}
    {% set filteredEntries = filteredEntries|merge([entry]) %}
{% endif %}

If a block matches the handle you’re looking for (in this example, formEmbedBlock), we add that entry to our filtered results array.

Step 4: Display the results

{% for entry in filteredEntries|unique %}
    <p>{{ entry.title }} ({{ entry.url }})</p>
{% endfor %}

Lastly, we loop through our filtered entries and display them. The |unique filter makes sure we don’t show duplicate entries since an entry might use the same block type multiple times.

Customizing and Using for Your Needs

To use this code:

  1. Replace myMatrixFieldHandle with your actual Matrix field handle
  2. Replace formEmbedBlock with the block type handle you're searching for
  3. Create a new template in your Craft templates directory and paste this code in
  4. Visit that template's URL in your browser

You can also modify the output section to display additional information, such as:

{% for entry in filteredEntries|unique %}
    <p>
        <strong>{{ entry.title }}</strong><br>
        Section: {{ entry.section.name }}<br>
        URL: <a href="{{ entry.url }}">{{ entry.url }}</a><br>
        Edit: <a href="{{ entry.cpEditUrl }}">Edit in Control Panel</a>
    </p>
{% endfor %}

Use Cases

This technique is particularly useful when you're:

  • Deprecating a block type: Before removing a Matrix block from your field layout, you'll want to know which entries still use it so you can update them first.
  • Troubleshooting: If a particular block type is causing issues, you can quickly identify all affected entries.
  • Content auditing: Understanding which content types are actually being used (versus just sitting unused in your field layout) can inform future design decisions.
  • Planning migrations: If you're restructuring your content model (which is what I had to do recently), knowing where specific blocks are used helps you plan the transition.

Performance Considerations

Keep in mind that this approach loads all entries with your Matrix field into memory and loops through their blocks. For sites with thousands of entries, this could be slow or memory-intensive.

If you're working with a large dataset, consider:

  • Adding additional filters to your initial query (like .section('news') or .dateCreated('>= 2024-01-01')) to narrow the scope. Simply imposing a limit (with .limit()) works too.
  • Running this as a console command or queue job rather than in a template.
  • Using a direct database query for very large datasets (though this requires more technical knowledge).

For most typical Craft sites, though, this Twig approach works perfectly well.

Conclusion

As you can see, this technique is straightforward and gives you visibility into how your content is structured. It makes it much easier to maintain and evolve your Matrix fields over time.

Have you found other clever ways to audit or search your Craft content? I'd love to hear about them – feel free to reach out on LinkedIn, Bluesky, or Mastodon.