Action Hook since 2.0.0

pre_get_posts

Modify any WP_Query before it runs

Description

pre_get_posts fires for every query — main and secondary. Always check is_main_query() (and is_admin()) or you'll silently break widgets, related-post queries, and REST requests.

When it runs

Runs for the main front-end query, admin list tables, and any custom WP_Query — every single instantiation.

Signature

do_action( 'pre_get_posts', WP_Query $query );

Parameters

  • $query WP_Query — The query object, passed by reference — modify it directly.

Examples

Basic

add_action( 'pre_get_posts', function( $query ) {
    if ( ! is_admin() && $query->is_main_query() && is_post_type_archive( 'book' ) ) {
        $query->set( 'posts_per_page', 24 );
    }
} );

Change how many books show on the archive without touching the theme's template.

Real case

add_action( 'pre_get_posts', function( $query ) {
    if ( ! is_admin() && $query->is_main_query() && is_search() ) {
        $query->set( 'post_type', [ 'post', 'book' ] );
    }
} );

Include a custom post type in front-end search results.

Common Use Cases

  • Change posts_per_page for an archive
  • Include/exclude post types from search
  • Reorder posts on a custom query
  • Restrict a query by taxonomy or meta

Common mistakes

  • Forgetting the is_main_query() and !is_admin() checks — the callback then also fires on admin list tables, widgets, and unrelated secondary queries

Related hooks

FAQ

Why did my widget's post list get shortened after I used pre_get_posts?

You likely modified every WP_Query, not just the main one. Add $query->is_main_query() to the condition.

Source: wp-includes/class-wp-query.php

Group wizard

One session: this hook, then each related_hooks entry. Walk it and tell us what to change.

pre_get_posts → template_redirect

functions.php — pre_get_posts
functions.php
PHP pre_get_posts · Hook 1 of 2 · Step 1 of 6

Practice the pre_get_posts WordPress action hook in our interactive sandbox — a VS Code-style editor with a step-by-step pre_get_posts tutorial, add_action exercises, and instant feedback. No local WordPress install required.