How to exclude posts by tag, and create iterating counter variable using blog_recent_posts()

Hello,

I’m creating a custom module for pages, not blog single or listing templates. I have to create a module that shows the three most recent blog posts. However, the first post has be to the most recent post in a specific category, then the other two need to be the most recent post not in that same category.
I was able to get the first post using

{% set tag_posts = blog_recent_tag_posts('default', 'specific-tag', 1) %}
{% for tag_post in tag_posts %}
<div class="cell medium-4">
 <div class="recent-post company-news text-center">
 <div class="featured-image">
 <img src="{{ tag_post.featured_image }}" alt="{{ tag_post.name }}">
 </div>
 <div class="post-title">
 <h3>{{ tag_post.name }}</h3>
 </div>
 <div class="publish-date">
 {{ tag_post.publish_date|datetimeformat('%B %e, %Y') }}
 </div>
 <div class="read-more">
 <a href="{{ tag_post.absolute_url }}" class="button">Read More</a>
 </div>
 </div>
</div>
{% endfor %}

The problem I’m running into is getting the other two. I first tried using the blog_recent_posts() to grab some posts, loop through them and display post not in the category, using an incremented value to keep count. Since I don’t know won’t know how many posts it may need to skip over to find one not in the specfic topic, I’m just grabbing 20 post to be safe.
This is what I’ve tried doing. I’m normally a php developer, so I’m not great with HubL yet. So I’m very aware I’m probably approaching the wrong. But I’m having trouble finding any help in the docs that will work for my situation.

{% set posts = blog_recent_posts('default', 20) %}
{% set counter = 1 %}

{% for post in posts %}
 {% if counter <= 2 %}
 {% for topic in post.topic_list %}
 {% unless topic.name == 'Specific Tag' %}
 <div class="cell medium-4">
 <div class="recent-post">
 <div class="featured-image">
 <img src="{{ post.featured_image }}" alt="{{ post.name }}">
 </div>
 <div class="post-title">
 <h3>{{ post.name }}</h3>
 </div>
 <div class="publish-date">
 {{ publish_date|datetimeformat('%B %e, %Y') }}
 </div>
 <div class="read-more">
 <a href="{{ post.absolute_url }}" class="button">Read More</a>
 </div>
 </div>
 </div>
 {% set counter = counter + 1 %}
 {% endunless %}
 {% endfor %}
 {% endif %}
{% endfor %}

So not only is this still printing all 20 posts, letting me know my counter variable and incrementing is not working, but it’s also printing each post twice and is still showing posts that have the specific tag assigned. So it’s not working at any level lol.
Any help would be greatly appreciated. And just to reiterate it, this is a custom module meant for pages (not blog) on the same Hubspot account as the blog.

Hi @KiwiCreative, if I understand you properly, this is what you have and what you need:
- You have the first blog of the 3 you want to show
- You need to find 2 blogs more (recent blogs) that do not include the same tag as the first one
If the previous is correct, what about trying something like this?

{% set posts = blog_recent_posts('default', 20) %}
{% set tag = 'your_tag_name' %}
{% set counter = 0 %}

{% for post in posts %}
 {% if tag in post.tagList %}
 {# ENTERS HERE IF THE ARTICLE CONTAINS THE TAG #}
 {% else %}
 {% if counter < 2 %}
 <div class="cell medium-4">
 <div class="recent-post">
 <div class="featured-image">
 <img src="{{ post.featured_image }}" alt="{{ post.name }}">
 </div>
 <div class="post-title">
 <h3>{{ post.name }}</h3>
 </div>
 <div class="publish-date">
 {{ publish_date|datetimeformat('%B %e, %Y') }}
 </div>
 <div class="read-more">
 <a href="{{ post.absolute_url }}" class="button">Read More</a>
 </div>
 </div>
 </div>
 {% set counter = counter + 1 %}
 {% endif %}
 {% endif %}
{% endfor %}

In this code (that has not been tested, it’s just to guide you), what I suggest is looping over your recent posts and if the tag is not present on the tagList of a blog post AND the counter variable is less than 2, then show the article. So whenever it reaches 2 articles, it will stop showing more even though the loop will continue.

Does that makes sense? :slightly_smiling_face:

Hi @albertsg

Thank you very much for taking the time to help me out. Unfortunately, that did not resolve my issue. The result only returned one post and was the exact same post that I grabbed in the first column (the one that is working as it should). I tried making a couple adjustments like moving the counter interation up one level, I tried using topic_list rather than tagList. But all returned the same result.
Here is my updated code and a screenshot of the result. You will notice I changed one thing in the code, to use “unless” rather than the else part of the if statement. From my understanding, the unless statement is the inverse of an IF, which is exactly what you were doing. I tried both ways and had the same result.
In my screenshot, I’m printing the topic_list so that you can see the topics/tags. But since they’re the same post, that would be obvious. In this example, the tag I’m trying to exclude from the last two results is “cash-management”.
Here is my complete module code as it stands now. Any additional help or advice would be much appreciated.

<div id="recent-blog-posts-{{ name }}" class="recent-blog-posts">
 <div class="grid-x grid-padding-x">
 {% set tag_posts = blog_recent_tag_posts('default', 'cash-management', 1) %}
 {% for tag_post in tag_posts %}
 <div class="cell medium-4">
 {{ tag_post.topic_list }}
 <div class="recent-post text-center">
 <div class="featured-image">
 <img src="{{ tag_post.featured_image }}" alt="{{ tag_post.name }}">
 </div>
 <div class="post-title">
 <h3>{{ tag_post.name }}</h3>
 </div>
 <div class="publish-date">
 {{ tag_post.publish_date|datetimeformat('%B %e, %Y') }}
 </div>
 <div class="read-more">
 <a href="{{ tag_post.absolute_url }}" class="button hollow green">Read More</a>
 </div>
 </div>
 </div>
 {% endfor %}

 {% set posts = blog_recent_posts('default', 20) %}
 {% set tag = 'cash-management' %}
 {% set counter = 1 %}

 {% for post in posts %}
 {% unless tag in post.tagList %}
 {% if counter < 2 %}
 <div class="cell medium-4">
 {{ post.topic_list }}
 <div class="recent-post text-center">
 <div class="featured-image">
 <img src="{{ post.featured_image }}" alt="{{ post.name }}">
 </div>
 <div class="post-title">
 <h3>{{ post.name }}</h3>
 </div>
 <div class="publish-date">
 {{ post.publish_date|datetimeformat('%B %e, %Y') }}
 </div>
 <div class="read-more">
 <a href="{{ post.absolute_url }}" class="button hollow green">Read More</a>
 </div>
 </div>
 </div>
 {% set counter = counter + 1 %}
 {% endif %}
 {% endunless %}
 {% endfor %}
 </div>
</div>

So I finally figured it out! You got me almost there @albertsg . The issue was the check for the topic name in the topic list. Here is my updated code, I’ve been testing multiple different topics and it seems to be working perfectly now. Here is my code in case it will help anyone else in the future.

<div id="recent-blog-posts-{{ name }}" class="recent-blog-posts">
 <div class="grid-x grid-padding-x">
 {% set tag_posts = blog_recent_tag_posts('default', 'cash-management', 1) %}
 {% for tag_post in tag_posts %}
 <div class="cell medium-4">
 {{ tag_post.topic_list }}
 <div class="recent-post company-news text-center">
 <div class="featured-image">
 <img src="{{ tag_post.featured_image }}" alt="{{ tag_post.name }}">
 </div>
 <div class="post-title">
 <h3>{{ tag_post.name }}</h3>
 </div>
 <div class="publish-date">
 {{ tag_post.publish_date|datetimeformat('%B %e, %Y') }}
 </div>
 <div class="read-more">
 <a href="{{ tag_post.absolute_url }}" class="button hollow green">Read More</a>
 </div>
 </div>
 </div>
 {% endfor %}

 {% set posts = blog_recent_posts('default', 20) %}
 {% set tag = 'Cash Management' %}
 {% set counter = 0 %}

 {% for post in posts %}
 {% unless tag in post.topic_list|map('name') %}
 {% if counter < 2 %}
 <div class="cell medium-4">
 {{ post.topic_list }}
 {{ counter }}
 <div class="recent-post text-center">
 <div class="featured-image">
 <img src="{{ post.featured_image }}" alt="{{ post.name }}">
 </div>
 <div class="post-title">
 <h3>{{ post.name }}</h3>
 </div>
 <div class="publish-date">
 {{ post.publish_date|datetimeformat('%B %e, %Y') }}
 </div>
 <div class="read-more">
 <a href="{{ post.absolute_url }}" class="button hollow green">Read More</a>
 </div>
 </div>
 </div>
 {% set counter = counter + 1 %}
 {% endif %}
 {% endunless %}
 {% endfor %}
 </div>
</div>

It was the

{% unless tag in post.topic_list|map('name') %}

part that seemed to do the trick.

Thanks again for your help @albertsg

Thanks for that solution. It looks as if you filtered out posts with unwanted tags after querying the database. If I only want to list 10 blog posts, I would need to estimate the percentage of blog posts that have unwanted tags and then query the database for more than the desired 10 blog posts. Do I understand that correctly?

Is there a way to enter the unwanted tags in the actual database query?

Is there a more flexible function that is similar to SQL’s Select statement?

THANK YOU,

Travis