Insert an Ad or Call to Action in The Middle of a WordPress Post
Have you ever seen a post that had an advertisement or a call to action half-way through or 30% through the blog post? Sure you have. If not, you can see one on any of our blog posts, like this one.
Here's how to do it. Add this to your functions.php file in your theme:
/**
* Insert call to action to middle of blog posts
*/
add_filter('the_content', 'prefix_insert_post_ads');
function prefix_insert_post_ads($content) {
if (strpos($_SERVER['REQUEST_URI'], '/glossary/') !== false) { // Ignore on custom post types, optional
return $content;
}
$ad_code = '
<div id="middle-post-cta">
<!-- Add your call to action HTML here -->
</div>
';
if (is_single() && !is_admin() && !is_single(1234)) { // Exclude post ID(s) here, optional
return prefix_insert_after_paragraph($ad_code, $content);
}
return $content;
}
function prefix_insert_after_paragraph( $insertion, $content ) {
$doc = new DOMDocument();
@$doc->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'));
$paragraphs = $doc->getElementsByTagName('p');
$targetParagraphId = round($paragraphs->length / 2);
$totalParagraphs = $paragraphs->length;
$inserted = false;
while(!$inserted && $targetParagraphId < $totalParagraphs) {
$paragraph = $paragraphs->item($targetParagraphId);
$parentTag = $paragraph->parentNode->nodeName;
if ( $parentTag != 'blockquote' && $parentTag != 'ul' && $parentTag != 'ol' && $parentTag != 'li' && !$inserted){
$newNode = $doc->createDocumentFragment();
$newNode->appendXML($insertion);
$paragraph->parentNode->insertBefore($newNode, $paragraph);
$inserted = true;
}
$targetParagraphId++;
}
$body = $doc->getElementsByTagName('body')->item(0);
return $doc->saveHTML($body);
}
There's a few parts to this.
First, you have the ability to ignore this on certain categories or custom post types by adding a URL pattern to ignore. In this code, you'll see we have our /glossary/ custom post type as an example, since we don't want to put call to actions on these shorter posts.
If you don't need this part, simply comment out these three lines for now:
// if (strpos($_SERVER['REQUEST_URI'], '/glossary/') !== false) { // Ignore on custom post types, optional
// return $content;
// }
Next, excluding post IDs. This is if you have a special post that you want to keep advertisement-free. You can add the post ID here (replace 1234 with the post ID), and it will add it to all posts except for that one post:
if (is_single() && !is_admin() && !is_single(1234)) {
Or, if you want to add multiple:
if (is_single() && !is_admin() && !is_single(1234) && !is_single(1235) && !is_single(1236)) {
Or, if you have an entire category that you want to skip, you can use:
if (is_single() && !is_admin() && !has_category('Fishing')) { // Replace with your category
Lastly, this line is what controls where the call to action is inserted. I have it set to insert it half way through the post, so I divide the post by 2 and round to the nearest paragraph:
$paragraph_id = round(count($paragraphs) / 2);
But, if you want to make it appear earlier in the article, you can make it show up 33% through the article by dividing by 3 instead:
$paragraph_id = round(count($paragraphs) / 3);
This code is also configured to ignore blockquote, ul, li, and ol tags. You don't want it adding your HTML code inside a bullet point list or within a quote, after all!
I hope this helps! Please let me know if you have any questions in the comments and I'll get back to you very quickly.
October 23, 2024
hey so i was just wondering how do you think i can change this up to make it work on pages that have a bunch of categories? 😅
November 07, 2024
Hey Krystal!
You should definitely sort your pages into categories and use special fields to set up your ads. This lets you have more control over where ads show up for each specific category. I've seen some clients who use plugins like Advanced Custom Fields to do this really well. It's definitely something worth trying out!
If you have any more questions or if you decide to try it please let me know how it turns out! 😊