How to Create Custom Blog Post Summaries for Blog Listing Pages

HubSpot Moderator

This is a guide for creating a separate field within the blog post editor in order to write a summary of the post, which will then display as the post's summary on the blog's listing pages. It's an alternative to using the beginning of the post body text or even the Meta Description, which I've seen used as well. This is something I've helped a few people to create, so I figured it might be helpful to others to have a guide written down. The common use case for something like this is when the opening text of a blog post isn't actually useful to display as summary text on a listing page.


The first step is to create a custom module. Name it "Blog Post Summary". You can change the name if you'd like, but just keep in mind that you'll need to then adjust some of the code below. Make the module available for blog templates and make it a local module. Add one text field and name the field "Summary Text". Don't add anything into the HTML + HubL field; we'll be printing our HTML through the blog content module's listing template. But by adding a field to a module like this, we can add text to this field from within the blog post editor, and then access it from the listing pages. Publish your module.


Now head to your blog template and add your newly created "Blog Post Summary" module. You can add it anywhere; I'd suggest somewhere in the footer. If you're using separate templates for post and listing pages, you'll need to add this module to the template for blog post pages.


Next, head into the listing template of the blog content module. And if you're using separate templates for listing and post pages, make sure you're now in the template for listing pages. Locate the code that you're currently using to display the blog post summaries. That might look something like this:



<p>{{ content.post_list_content|truncatehtml(200, "...", false) }}</p>



You're going to replace that code with the code below. Just a few things to keep in mind while you're doing this:


  1. If you've named your custom module or its field differently from how I have, that will need to be adjusted in this code below.
  2. There are two lines where, if a post doesn't have a custom summary, the first 200 characters of the post body will be pulled in. This is the default summary that's pulled from the post body field. If your "default" that you're replacing looks different (like for example if you're limiting to 300 characters instead of 200), you should adjust that in the code below.
  3. If you're not looping through the blog's contents dictionary with a loop like {% for content in contents %} , then you'll need to adjust the references in the below code from content to whatever you've named your variable. So if for example you're looping through the blog posts with {% for item in contents %} , then you'll want to use something like {{ item.post_list_content }} instead of {{ content.post_list_content }} .

So now replace the code that you're currently using to display blog post summaries with the following:



{# create variable so that we know if the module exists in the post's content dictionary #}
{% set blogPostSummaryState = false %}

{# loop through the post's modules #}
{% for module in content.widgets %}

  {% if module.label == "Blog Post Summary" %}

    {# we've found the module, so let's set our variable to true #}
    {% set blogPostSummaryState = true %}

    {# is there a value in the summary text field? if yes, print it #}
    {% if module.body.summary_text and module.body.summary_text != "" %}
      <p>{{ module.body.summary_text }}</p>
    {# if not, print the default summary #}
    {% else %}
      <p>{{ content.post_list_content|truncatehtml(200, "...", false) }}</p>
    {% endif %} {# end if module.body.summary_text and module.body.summary_text != "" #}

  {% endif %} {# end if module.label == "Blog Post Summary" #}

  {# we only want to run this bit once, so we do it in the last loop iteration #}
  {# this is for existing posts that haven't yet been updated, because they won't have the module show up in their content dictionary #}
  {% if loop.last %}
    {# if we didn't find our module, print the default summary #}
    {% if blogPostSummaryState == false %}
      {{ content.post_list_content|truncatehtml(200, "...", false) }}
    {% endif %} {# end if blogPostSummaryState == false #}

  {% endif %} {# end if loop.last #}

{% endfor %} {# end for module in content.widgets #}



I've added comments that I think make the code more understandable. But this is really all there is to it. You should now be able to head into the editor for one of your blog posts. You'll find a module "Blog Post Summary" with a field "Summary Text" that you can edit. Save and update the post with some text in there and then check the listing page again. You should see that its summary has updated.


You can optionally add filters to your summary field like |truncatehtml() (documented here: if you want to ensure uniformity on the listing page.


If anyone has questions about setting this up or if anyone has other methods or any improvements to my method, feel free to leave some comments.



Leland Scanlan

HubSpot Developer Support

0 replies

No replies on this post just yet

No one has replied to this post quite yet. Check back soon to see if someone has a solution, or submit your own reply if you know how to help! Karma is real.

Reply to post

Need help replying? Check out our Community Guidelines