We use cookies to make your viewing experience better. By accepting you consent, you agree to our Cookie policy

Improve your Craft CMS skills

How To List Number Of Entries In Craft CMS

10 min read
Shape April 2022 HR 189

Efficiently retrieving entry counts is crucial for performant Craft CMS projects, yet it's easy to hurt site speed with unoptimized queries. This guide provides targeted solutions to count entries fast, from leveraging Twig and JavaScript to intelligently caching and eager loading. Follow our strategic counting techniques to keep your Craft site speedy even at scale. Dramatically boost performance by counting entries the right way.

Craft CMS offers several efficient methods to count entries, including count() for quick totals, looping to accumulate filtered counts, search() for customized criteria, outputting directly in Twig templates, and JavaScript for dynamic real-time updates. Carefully selecting the optimal technique improves performance.

Counting Entries in Craft CMS

Overview of Entry Counting Techniques

Craft CMS offers several methods for efficiently retrieving entry counts, each with their own strengths depending on the specific use case. The count() function can quickly get a total count of entries in a section or across multiple sections. This works well when you need an overall count.

Looping through entries allows iterating over each one to accumulate a total count. This provides more flexibility to count entries matching certain criteria. The search() method also facilitates querying for filtered entry counts based on element criteria.

Outputting entry counts directly in templates is useful for displaying totals publicly. Twig's {% set %} tag can cache counts in variables for improved performance. For dynamic updating, JavaScript can fetch entry counts via AJAX requests.

Carefully selecting the optimal technique improves performance. Use count() and search() for simple overall counts. Opt for loops or JavaScript when needing filtered or frequently updated counts. Understanding the options helps choose the right approach.

Benefits of Optimizing Entry Counts

Optimizing entry count queries offers significant performance and efficiency improvements for Craft CMS sites. By caching counts instead of running complex database queries, page load times are reduced.

Counting entries can easily trigger N+1 query issues, causing excessive database hits. Optimizing avoids these problems, limiting index rebuilds from inefficient queries. Intelligently caching totals also prevents unnecessary calls to regenerate counts.

The cumulative effect is markedly faster response times. Pages load quicker by minimizing expensive operations. The frontend feels more responsive, improving user experience. Optimized entry counts save server resources too.

For large entries, these optimizations become even more impactful. Craft CMS sites with hundreds or thousands of entries benefit immensely from proper count querying and caching. Just a few tweaks can translate to major speed boosts.

Using the count() Function for Entry Counts

count() Query Examples

The count() function in Craft CMS offers a straightforward way to retrieve total entry counts. For example, Entry.count() gets the total count of all entries across all sections.

To count entries in a specific section:

{% set totalNews = craft.entries.section('news').count() %}

Filters can target counts even further:

{% set publishedNews = craft.entries.section('news').status('live').count() %}

count() works great for quick overall entry totals. The simple syntax and ease of use makes it ideal for basic count needs.

count() Performance Considerations

While convenient, using count() without optimizations can hurt performance in Craft CMS. Calling it repeatedly triggers excessive database queries, especially if using unfiltered queries on large entry sets.

Every count() call must scan all entries, becoming increasingly expensive at scale. Without caching or targeting filters, thousands of entries means thousands of database hits for every count.

Performance issues compound on pages with multiple count() calls. Slow load times result as the database struggles under the load. Proper indexing and caching becomes critical to optimize count().

When to Use count() for Entry Counts

The count() function works best for straightforward total counts directly in templates. A common use case is displaying a simple entry count publicly, like "5 blog posts found".

For more complex or dynamic counting needs, count() has limitations. Alternate options like looping may be better for filtered counts. Updating counts frequently via JavaScript is also easier with other techniques.

Overall count() is a good option when basic entry totals are sufficient. It's simple, fast, and avoids more complex logic when a quick total count is all that's needed. Just be mindful of performance, and optimize queries for large entry sets.

Looping Through Entries Efficiently

Pagination for Large Entry Sets

When looping through a large number of entries in Craft CMS, pagination is key for optimized performance. The .limit() and .offset() parameters on entry queries allow fetching a subset of entries per page.

For example:

{% set entries = craft.entries.section('blog').limit(10).offset(0) %}

This loads the first 10 entries, with .offset() specifying the starting point. Subsequent pages can increment the offset to lazy load the next set.

Paginating entries avoids loading hundreds or thousands of entries at once. By working in smaller batched sets, databases and servers aren't overwhelmed.

Using Cache Keys to Limit Queries

Looping through entries normally triggers a fresh database query for every iteration. Cache keys allow caching the looped entries to prevent excessive queries.

The cache key defines the criteria for cache invalidation. For example:

{% cache using key 'entries-blog-section' %}

{% for entry in entries %}


{% endfor %}

{% endcache %}

Now the looped entries are cached until any blog section entry changes. The cache key limits queries while keeping data fresh.

Careful cache invalidation is still needed to purge stale data. But cache keys effectively optimize entry loops and restrict queries.

Additional Loop Optimization Tips

  • Set limits on looped entry criteria to prevent runaway queries on uncontrolled sets

  • Avoid dynamic or frequently changing sort orders that prevent effective caching

  • Simplify entry criteria to allow more caching opportunities

  • Fetch only the data needed in each iteration instead of full entries

  • Use eager-loading for any relational data to avoid N+1 queries

  • Load assets simultaneously with entries to reduce separate queries

  • Consider caching at the template level to minimize duplicated effort

Optimized entry loops are vital for performant Craft CMS sites. A few key techniques go a long way to efficient iteration.

Searching Entries for Targeted Counts

Search Query Examples for Counts

Craft's search feature allows retrieving targeted entry counts based on specific criteria. For example:

{% set newsCount = craft.entries()

.search('section:news status:live postDate:>='~now|date_modify('-1 month'))

.count() %}

This counts live news entries from the past month. Search enables flexible date, attribute, and relational filters for custom counts.

Multiple search parameters can be combined for very customized counts. Specific entry types, categories, authors, and more can be targeted.

Eager Loading to Optimize Search

When counting entries from search results, eager loading any relations optimizes performance. For example:

{% set entries = craft.entries()

.with(['author', 'categories'])


.count() %}

Eager loading avoids N+1 query issues that would hit the database for every entry's relations separately. A single optimized query retrieves the entries and related data.

For large result sets, the difference can be dramatic, from thousands of queries to just one. Always eager load for search counts.

Additional Search Count Tips

  • Index search columns used for filters for faster search performance

  • Be as specific as possible with search criteria to allow better caching

  • Watch out for eagerness vs lazy loading based on context

  • Avoid search parameters that prevent caching like random ordering

  • Consider caching search results and then displaying counts

  • Too many search parameters can result in overly complex queries

  • Test searches at scale to identify expensive operations

Craft's search makes retrieving targeted entry counts easy. With proper optimization and indexing, it's a powerful tool for flexible and performant entry counting.

Outputting Entry Counts in Templates

Twig Template Examples

Twig makes it easy to output entry counts directly in Craft CMS templates. For example:

<p>{{ entryCount }}</p>

<p>Total entries: {{ entryQuery.total }}</p>

The entryCount variable contains the cached count, while entryQuery.total outputs the total right from the query.

Other examples include:

{% set entryCount = craft.entries.section('news').count() %}

{% set entries = craft.entries.section('news') %}

<p>{{ entries|length }}</p>

So assigning to variables, Twig filters like length, or query objects can all display counts.

Caching Count Variables

Caching entry counts in Twig variables prevents repeated, expensive queries:

{% set entryCount = craft.entries.section('news').count() %}

Now entryCount is cached until the cache is cleared . No matter how many times it's output, the count is not re-queried.

This caching optimizes performance dramatically compared to calling .count() repeatedly. Variables also enable reusing the count efficiently.

Displaying Counts Conditionally

Conditionals allow selectively outputting counts only when needed:

{% if entryCount %}

<p>There are {{ entryCount }} total entries<p>

{% endif %}

This avoids even caching or querying for a count if unused on a given page.

Similarly, switch tags can display different text based on the count. Counts can also be limited to specific templates where needed.

Outputting entry counts directly in templates provides tons of flexibility. With proper caching and conditionals, it's an optimized approach.

Fetching Entry Counts via JavaScript

Calling API Endpoints for Counts

JavaScript enables retrieving entry counts from frontend controllers and API endpoints. For example:


.then(response => response.json())

.then(data => {

// Display count from data.count


The endpoint runs a query and returns the count as JSON. Axios, jQuery, or any HTTP client can call these endpoints.

This allows updating counts in real-time without full page loads. The frontend stays responsive and fast.

Client-Side Caching

Caching entry counts in client storage avoids expensive API requests:

let count = localStorage.getItem('entryCount');

if (!count) {

// Fetch count via API

localStorage.setItem('entryCount', count);


Now the count is only fetched when undefined. Subsequent requests read from cache until invalidated.

This caching is crucial for performance. Without it, heavy API requesting degrades experience, especially on slower networks.

Use Cases for JavaScript Counts

JavaScript counting shines for dynamic displays that update in real-time. As new entries are added, counts can increment automatically without refreshing.

It also prevents full page loads just to get updated counts. The API can be called in the background as needed.

JavaScript enables counting entries without hard page reloads. For frequently changing data, it's more performant and flexible.

Optimizing Entry Count Performance

Database and Cache Backends

Enabling caching and query caching dramatically improves entry count performance in Craft CMS.

Redis provides a fast cache backend to offload count caching from the database. Count queries hit Redis instead of running heavy database operations.

Database query caching caches the SQL queries and results. This prevents identical count queries from hitting the database at all.

Together, Redis and query caching deliver optimized performance by eliminating unnecessary queries. Entry counts come from fast in-memory caches.

Eager Loading Relations

Eager loading any relations avoids N+1 queries that can plague count performance:

{% set entries = craft.entries()

.with(['categories', 'author'])

.all() %}

{{ entries|length }}

This single queryeager loads the categories and authors with the entries. Without it, separate queries would be executed per entry relation.

For large entry sets, eager loading is critical to avoid thousands of extra queries. Always load related data upfront when counting.

Additional Tips for Optimization

  • Limit index rebuilds from unoptimized queries hammering the database

  • Simplify criteria to allow better caching opportunities

  • Use the optimize command to index columns used for filtering

  • Enable template level caching to prevent duplicated querying effort

  • Test any dynamic parameters for their performance impact

  • Minimize separate asset queries when eager loading entries

  • Set environment variables to cache counts in production environments

  • Keep an eye on slow database queries that point to count optimizations

Entry counting in Craft CMS offers many levers for performance. Fine-tuning caching, eager loading, indexing, and more results in lightning fast count queries.

Comparing Entry Counting Techniques

When to Use Each Technique

Choosing the best entry counting technique depends on the specific use case and requirements:

  • count() - Simple overall counts displayed in templates

  • Loops - Filtered, complex, or frequently changing counts

  • Search - Targeted counts by custom criteria

  • Templates - Public display of entry counts

  • JavaScript - Dynamic updating of counts in real-time

count() is fastest for basic counts but inflexible. Loops offer more customization while search provides targeted filtering. Templates work well for display purposes while JavaScript enables live updating.

Tradeoffs and Considerations

There are tradeoffs to each approach:

  • count() is very fast but less customizable

  • Loops are flexible but can hurt performance without optimization

  • Search enables advanced filtering at the cost of complexity

  • Templates simplify display but duplicate query logic

  • JavaScript adds dynamism but requires API and client-side work

Factor in performance needs, caching abilities, display requirements, and count complexity when deciding. Optimally combine techniques to leverage their strengths.

Examples and Sample Use Cases

  • Use count() to show total blog posts in a sidebar widget

  • Leverage search to display entries from the past month

  • Loop through entries to filter and display authors' post counts

  • Update entry counts dynamically in real-time with JavaScript

  • Show paginated entry listings with total count in templates

The technique depends on the context. Evaluate the options against requirements to pick the best approach or combination of techniques.

Shape April 2022 HR 202
Andy Golpys
- Author

Andy has scaled multiple businesses and is a big believer in Craft CMS as a tool that benefits both Designer, Developer and Client. 

Show us some love
Email Us
We usually reply within 72 hours
Agency Directory
Submit your agency
Affiliate Partners
Let's chat