OC: Blog Post Call to Action

How to add a call to action after every blog post

Posted by admin on May 08, 2023


(skip to the next section to dive straight into the technical details)

I have a renewed desire to blog consistently about software and technology. My hope is two fold: first, to help others learn about the technology I'm most passionate about; and two, in doing so to gain a deeper understanding about that technology.

My current obsession is with Orchard Core, a framework built atop ASP.NET and .NET that provides a content management system as well as a modular first approach to software architecture. Right now, I'm working my way through the content management features of Orchard Core to more deeply understand its capabilities and to experience how a less technical creator might use it to say launch a new blog.

In fact, my own blog here is built and managed using Orchard Core - I recently migrated from a custom .NET web application I built and attempted to turn into my own content management system. Once I learned about Orchard core, I realized it aligned exactly with my needs and desires. So far the experience has been very positive.


A popular tip from twitter on how to grow an audience for your blog or newsletter suggests putting a so-called "call to action" at the end of your post whether it be a blog post or twitter thread. It invites the reader to engage with you in some way and learn more about the information you're providing. I noticed my own blog posts were ending with the same, "For more information, follow me on twitter..." section that invited the reader to interact with me on twitter. You can scroll to the bottom of this post and see it.

If like me you grow tired of copying and pasting the same call to action at the end of every blog post, read on - there is a solution to this problem. With Orchard Core, you can use a feature called Widgets to automatically put content on certain parts of your site so you don't need to manually copy/paste it to every content item.


In short, you need to do the following things to automatically add a call to action to the end of every blog post in Orchard Core. Note that there are multiple ways to achive this affect, and this way allows you to do so without any custom code.

  1. Override the default Layout shape from TheBlogTheme to create a new content zone
  2. Create a new layer that targets blog posts
  3. Add a widget to the new content zone and new layer
  4. Optionally, override the Widget template to match the blog post style

If you need or want to learn more about the widgets feature in Orchard Core, you can read the documentation.

If you need or want to know about Orchard Core in general, you can also... read the documentation.

Override TheBlogTheme Default Layout

TheBlogTheme does not by default provide a zone between the Content and the Footer zones. You need to provide that yourself. If you have your own theme that uses TheBlogTheme as it's base, you can simply override the default Layout in your own Layout.cshtml or Layout.liquid template. If you're like me and want to avoid your own theme as much as possible, you can override the layout through the Admin UI using the Templates feature which allows you to override templates in your active theme.

Read more about templates in the Orchard Core documentation.

Log in to the Admin UI and navigate to Design->Templates - if you don't see that options you must find/enable the Templates feature under Configuration->Features page.

Click Add Template and give it a Name value of Layout. It's important that Layout is used for the name because that is how Orchard Core will know to use your template as an alternative to the default Layout from TheBlogTheme.

Copy and paste the following code into the Content section of your new Layout template.

<!DOCTYPE html>
<html lang="{{ Culture.Name }}">
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>{{ "PageTitle" | shape_new | shape_stringify }}</title>
    {% resources type: "Meta" %}
    {% link type:"image/x-icon", rel:"shortcut icon", href:"~/TheBlogTheme/favicon.ico" %}
    <!-- Font Awesome icons (free version)-->
    {% style name:"font-awesome", version:"6", at:"Head" %}
    <!-- Google fonts -->
    <link href='https://fonts.googleapis.com/css?family=Lora:400,700,400italic,700italic' rel='stylesheet' type='text/css'>
    <link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
    <!-- Core theme CSS (includes Bootstrap) -->
    {% style name:"theblogtheme" %}
    {% style name:"theblogtheme-bootstrap-oc", version:"1" %}
    {% script name:"theblogtheme", at:"Foot" %}

    {% resources type: "HeadScript" %}
    {% resources type: "HeadLink" %}
    {% resources type: "Stylesheet" %}
    {% render_section "HeadMeta", required: false %}
<body dir="{{ Culture.Dir }}">
    <nav class="navbar navbar-expand-lg navbar-light" id="mainNav">
        <div class="container px-4 px-lg-5">
            <a class="navbar-brand" href="{{ '~/' | href }}">{{ Site.SiteName }}</a>
            <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
                <span class="sr-only">{{ "Toggle navigation" | t }}</span>
                {{ "Menu" | t }} <i class="fa fa-bars" aria-hidden="true"></i>
            {% shape "menu", alias: "alias:main-menu", cache_id: "main-menu", cache_fixed_duration: "00:05:00", cache_tag: "alias:main-menu" %}
    {% render_section "Header", required: false %}
    <div class="container px-4 px-lg-5 mb-4">
        <div class="row gx-4 gx-lg-5 justify-content-center">
            <div class="col-md-10 col-lg-8 col-xl-7">
				{% render_section "Messages", required: false %}
                {% render_body %}
                {% render_section "AfterContent", required: false %}
    <footer class="border-top">
        {% render_section "Footer", required: false %}
    {% resources type: "FootScript" %}

This is a modified version of the TheBlogTheme's default Layout template. The notable difference is the extra section named AfterContent which appears after the render_body section.

{% render_section "AfterContent", required: false %}

Click Save.

This effectively creates a new zone named AfterContent in which you can place your call to action widget.

Also note, you may want to check the Orchard Core source code to ensure the default layout of TheBlogTheme has not changed since the time of this writing. If it has, then you need to copy/paste that version. You may want to check if any new zones have already been added.

You can view the latest version here on GitHub because Orchard Core is open source.

Create a New "Every Blog Post" Layer

Orchard Core provides a wide breadth of features that you'd expect from a content management system. And these modular features come together to provide great power in customizing its content.

The next step is to create a new layer that will be active for all the blog posts on your site but not the other pages of your site.

On the Design->Widgets page, click the Add button under the Layers section to add the new layer. Give the new layer a meaningful name like Blog Post CTA (for call to action).

Next, click Add next ot the Rules section of the Edit Layer page to tell Orchard Core under what conditions the layer should be active and visible. Specifically, find the Content type condition and click Add.

You should now see the Edit Rule page where you can define the rule conditions. Enter Equals and BlogPost as values for the the Operation and Value fields, respectively.

Click Save - you now have a new Blog Post layer you can use in conjunction with your new AfterContent zone. With them you can create your new call to action widget to automatically display on every blog post.

Create your Call to Action Widget

Navigate back to the Design->Widgets page where you can add widgets to your zones. You will notice (assuming you haven't already done the following step) that your AfterContent zone is not there underneath the Content and Footer zones. This is because you need to enable your new zone in the widget settings.

Navigate to Design->Settings->Zones which gives you a "Available zones for Layers" field to configure which zones are available for use in Layers. Add AfterContent to this list. You should see the following assuming you currently only have the default set of zones that come with TheBlogTheme.

Content, Footer, AfterContent

Navigate back to the Design->Widgets screen and see your AfterContent zone is now available to add widgets.

Click Add Widget and choose Paragraph which allows you add the content for your call to action. For title, enter something meaningful like CTA - Follow on Twitter, leave the Render title box unchecked. For The layer the widget should be associated with. select your Blog Post CTA layer you added in the previous step. In Content put your call to action - notice you have a WYSIWYG editor to make it easy to format HTML, add links, etc.

As an example, you can add something like the following (obviously use your own twitter handle).

If you found value in this post, consider following me on twitter @davidpuplava for more valuable information about software and other topics.

Then highlight the twitter handle, click the insert link button of the WYSIWYG editor and enter your twitter profile URL into the URL field.

Another option is to add a "Subscribe to my newsletter" call to action which I will demonstrate in a future post.

Note: You can also use the RawHtml widget rather than the Paragraph widget and just write the HTML with the <a href...></a> tag yourself. I chose Paragraph because it is more user friendly for a non-technical creator.

Click Save and then Actions->Publish Draft for your new widget.

Navigate to one of your blog posts and see your call to action at the end of the post!

You may notice however that the indentation does not match the rest of the blog post. We will fix that in the next section.

Optional - Match Widget Style to Blog Post

The widget is published with its own wrapper HTML tags and classes that allows for the display of title and other styling. The Widget documentation (linked here) indicates that a common task is to remove the Widget wrapper tags. You can do this using the Templates feature just like you did before with overriding the Layout template to add the AfterContent zone.

Naviate to Design->Templates and click Add Template. The Name should be the following to exactly match the widget in the AfterContent zone.


Note: there is a single underscore between "Widget" and "Wrapper" but a double underscore before "Zone" and before "AfterContent". This follows the conventions that Orchard Core uses to identify the specific conditions for when the template is overriden. More information on overriding templates can be found in the documentation.

In the Content field, simply add the following.

{{ Model.Content | shape_render }}

Click the Save button.

And that's it! You should now see your call to action at the end of every blog post.

If you look at the text just below the tags on this blog post, you'll see my call to action. This is automatically added to every blog post using the method described in this post.

If you found value in this post, consider following me on X @davidpuplava for more valuable information about Game Dev, OrchardCore, C#/.NET and other topics.