Adding ads code between comments

The end-callback of wp_list_comments()

One way is to use the end-callback argument in:

wp_list_comments( [ 
    'end-callback' => 'wpse_comments_ads_injection',
    ... other arguments ...
], $comments );

in addtion to your other wp_list_comments arguments, by defining:

function wpse_comments_ads_injection( $comment, $args, $depth ) {
     static $instance = 0;
     $tag             = ( 'div' == $args['style'] ) ? 'div' : 'li';

     echo "</{$tag}><!-- #comment-## -->\n";

     if ( 0 === $instance % 2 ) {
         echo "<{$tag} class=\"comment__ad\">YOUR AD HERE!</{$tag}>";
     }

     $instance++;
}

where we do the counting with the static variable $instance that’s incremented for each call.

This should inject the defined comment ads, using either div or li tags, depending on the styling.

By using the end-callback, we don’t need to modify the comment callback, if we don’t need to, just to inject the ads. So if we need the default comment layout, we can also inject the ads this way.

One could additionally use the comment depth to control the ads display.

Note that the callback for both the callback and end-callback of wp_list_comments(), has three input arguments, not four.

The wp_list_comments_args filter

We can then adjust it further and use the wp_list_comments_args filter:

add_filter( 'wp_list_comments_args', function( $args ) {
    if ( ! isset( $args['end-callback'] ) ) {
        $args['end-callback'] = 'wpse_comments_ads_injection';
    }
    return $args;
} );

instead of modifying the the wp_list_comments() directly.

We can create a plugin for this or add this into the functions.php file in the current theme’s directory.

Introducing injection’s offset, rate and html

Then we can add a support for the injection’s rate, offset and html:

add_filter( 'wp_list_comments_args', function( $args ) {
    if ( ! isset( $args['end-callback'] ) ) {
        // Modify this to your needs!
        $args['end-callback'] = 'wpse_comments_ads_injection';
        $args['_ads_offset']  = 0;  // Start injecting after the 1st comment.
        $args['_ads_rate']    = 2;  // Inject after every second comment.
        $args['_ads_html']    = '<img src="http://placekitten.com/g/500/100" />';
    }
    return $args;
} );

where we adjust the end-callback with:

/**
 * Inject Ads To WordPress Comments - end-callback for wp_list_comments().
 *
 * The Ads HTML is sanitized through wp_kses_post().
 *
 * @version 1.0.11
 * @see https://wordpress.stackexchange.com/a/328155/26350
 */
function wpse_comments_ads_injection( $comment, $args, $depth ) {
    static $instance = 0;
    $tag             = ( 'div' == $args['style'] ) ? 'div' : 'li';
    $ads_rate        = isset( $args['_ads_rate' ] ) && $args['_ads_rate' ] > 0 
        ? (int) $args['_ads_rate' ] 
        : 2;
    $ads_offset      = isset( $args['_ads_offset' ] ) && $args['_ads_offset' ] > 0
            ? (int) $args['_ads_offset' ]
        : 0;
    $ads_html        = isset( $args['_ads_html' ] ) 
        ? wp_kses_post( $args['_ads_html' ] )
        : '';

    echo "</{$tag}><!-- #comment-## -->\n";

    if ( $ads_offset <= $instance && 0 === ( $instance - $ads_offset ) % $ads_rate && ! empty( $ads_html ) ) {
        echo "<{$tag} class=\"comment__ad\">{$ads_html}</{$tag}>";
    }

    $instance++;
}

Here’s a gist for the code to add into the functions.php file in the current themes directory.

This is untested, but I hope you can adjust this to your needs!