How to add elements inside a query loop

Hello,
I try to find a solution to add a div element inside my query loop let me explain:
I have a query loop of my CPT from jetengine named gallery, every n posts I want to add an advert from a CCT or CPT if it is simple.

So I have all my galleries displayed with my query loop and every 5 posts I want to display an ad of my cct.

Do you know how to do that if possible, I try everything I know

Thank you for your help

You can try a Listing Grid injections (module in JE), but you’ll have to use JE listing instead of bricks query loop

Yes you are right, but I switch to bricks because the html code is awesome and All JE elements are integrated with countless wraps and I try to get a quick and efficient site.

Here’s a clean solution to insert ads every 5 posts in your Bricks query loop:

Step 1: Create Helper Functions

Add these functions to your theme’s functions.php:

function get_loop_index() {
    $index = intval( Bricks\Query::get_loop_index() ) + 1;
    return $index ? $index : 0;
}

function is_fifth_post() {
    return get_loop_index() % 5 == 0;
}

// Register functions for Bricks echo
add_filter( 'bricks/code/echo_function_names', function() {
    return [ 'is_fifth_post', 'get_loop_index' ];
} );

Step 2: Set Up Your Query Loop Structure

In your Bricks template:

  1. Create your main Query Loop for your “gallery” CPT
  2. Inside the loop item, create a Container to hold both divs

Step 3: Create Two Divs Inside Loop Item

Div 1: Regular Gallery Post

  • Add a Div element with your normal gallery post content
  • Add condition: Dynamic data → {echo:is_fifth_post} → != → 1

Div 2: Advertisement

  • Add another Div element with your ad content (CCT query or manual ad)
  • Add condition: Dynamic data → {echo:is_fifth_post} → == → 1
  • Add nested Query Loop (set to your ads CPT with posts per page: 1) or just static HTML
2 Likes

There’s no clean way to do it. Only wrapping every entry in an additional parent, which does not allow you to create a clean DOM structure as shown above.

I made a feature request for a Query Loop Element that supports any number of root elements and supports your use case well

3 Likes

Great idea hope they implement it
thank you

Thank you I will test that solution

Totally agree with your points. A Query Loop element that supports multiple root elements would be a game-changer for these use cases. It would be much more flexible with fewer limitations. Would love to see this implemented in future updates.

2 Likes

It’s not working for me by the way I’m in v2 maybe something change with the new version.
Inside the builder I see the 2 divs but in front end only the first query is displayed the gallery one.

Make sure you have “Code execution” enabled in Bricks Settings → Custom Code for your user role (Administrator). The {echo:} functions won’t work without this setting enabled.

Good guess I didn’t enable code execution So I did it for admin and verif the code the fonctions are detected but still not working in front end same problem
Do you have an idea ?
For simplicity I just add a heading in the div2 to try it.

My mistake in the original solution. The conditions should be:

  • Ad div: {echo:is_fifth_post} == 1
  • Gallery div: {echo:is_fifth_post} != 1
2 Likes

yes it works now thank you for your help
I just find a “problem” with that solution, the fifth is replaced by the ads so the fifth of my gallery just disapear from my listing.
I thought that the ads will be inserted (added) but with this solution the ad replace a post, I can handle it but for sure it’s not the best solution.
thank you anyway for your code

Just don’t add the second condition and both will be shown. But you’ll have a hard time styling that mess of an HTML tree.

That’s the reason why multiple root entries need to be supported in query loops and this would be super easy.

Here’s a solution that inserts ads every 5 posts without replacing them:

Add to functions.php:

add_filter( 'bricks/setup/control_options', function( $control_options ) {
    $control_options['queryTypes']['gallery_with_ads'] = 'Gallery with Ads';
    return $control_options;
});

add_filter( 'bricks/query/run', function( $results, $query_obj ) {
    if ( $query_obj->object_type !== 'gallery_with_ads' ) {
        return $results;
    }

    $posts_per_page = $query_obj->settings['posts_per_page'] ?? 10;
    $orderby = $query_obj->settings['orderby'] ?? 'date';
    $order = $query_obj->settings['order'] ?? 'DESC';
    $offset = $query_obj->settings['offset'] ?? 0;
    $paged = get_query_var('paged') ? get_query_var('paged') : 1;
    
    $posts = get_posts([
        'post_type' => 'gallery',
        'posts_per_page' => $posts_per_page,
        'post_status' => 'publish',
        'orderby' => $orderby,
        'order' => $order,
        'offset' => $offset + (($paged - 1) * $posts_per_page),
        'suppress_filters' => false
    ]);
    
    $ads = get_posts([
        'post_type' => 'ads',
        'posts_per_page' => -1,
        'post_status' => 'publish'
    ]);
    
    if (empty($ads)) {
        return $posts;
    }
    
    $combined_results = [];
    $ad_index = 0;
    
    foreach ($posts as $index => $post) {
        $combined_results[] = $post;
        
        if (($index + 1) % 5 === 0) {
            $ad = clone $ads[$ad_index % count($ads)];
            $combined_results[] = $ad;
            $ad_index++;
        }
    }
    
    return $combined_results;
}, 10, 2 );

add_filter( 'bricks/query/result_max_num_pages', function( $max_num_pages, $query_obj ) {
    if ( $query_obj->object_type !== 'gallery_with_ads' ) {
        return $max_num_pages;
    }
    
    $posts_per_page = $query_obj->settings['posts_per_page'] ?? 10;
    $total_posts = wp_count_posts('post')->publish;
    
    return ceil($total_posts / $posts_per_page);
}, 10, 2 );

In Bricks:

  1. Query Loop → Type: “Gallery with Ads”
  2. Template structure:
  • Div (Gallery): Condition {post_type} == gallery
  • Div (Ad): Condition {post_type} == ads

Both gallery and ad posts can use standard WordPress fields like {post_title}, {post_content}, {featured_image}, etc.

Result: gallery1, gallery2, gallery3, gallery4, gallery5, ad1, gallery6, gallery7, gallery8, gallery9, gallery10, ad2, etc.

Note: Make sure to test thoroughly with your specific setup and pagination requirements.

Alternative: As Maexxx mentioned, you can also use the original approach with is_fifth_post - just don’t add the second condition and both divs will be shown if the HTML structure doesn’t bother you.

1 Like

Thank you very much I will test this solution

Hello, @aidardev, I modify some things and use CPT instead of CCT to make it work with your code
And it works good thank you very much
One more thing, I use some options in my previous query loop with the UI interface, like infinite scroll, ajax loader, exclude current post and some tax query.
Can you tell me where I can extract/find the informations of my query loop so I can add it to the code you send me ? maybe in the Database ?
Thanks for your help

Another thing I just notice, the {post_url} doesn’t work in a link field it’s displayed in the basic text module but when I add it to a link I have the current page url and not the post one.
In a condition I add post_id and this the id of the current page and not the post one also.
Do you have an idea ? I try every modules. the featured image is displayed like the post title.
I try in a template but no success