Skip to main content

Templates

Templates are user-defined, dynamic, reusable snippets of HTML. The publisher provides an API to every piece of data related to your podcast. Using templates, you can display every detail in every layout you like.

Twig is used to make templates dynamic. Printing a variable in Twig looks like this:

{% raw %}
<strong>{{ podcast.title }}</strong>
{% endraw %}

You can iterate over a list of items:

{% raw %}
<ul>
{% for episode in podcast.episodes %}
<li>
<a href="{{ episode.url }}">
{{ episode.title }}
</a>{{ episode.subtitle }}
</li>
{% endfor %}
</ul>
{% endraw %}

These are the basics. You can refer to the Twig Documentation for all available options.

Creating Twig Templates — For Podlove Publisher Users

To create a template, go to Podlove → Templates and click "Add New".

The ID is used to reference the template from your episodes or pages. Choose a descriptive name. The fun starts below. The HTML Template is a freeform textfield. Write HTML/Twig there. All template variables and WordPress shortcodes are available. Click save when you are done.

Go to any post, page or episode and paste the template shortcode. It should look like this:

[podlove-template template="episode"]

Save and view the edited page. You should see the contents of your template. You can now go back to the template and edit until you like the results.

Episode Templates

Templates which are used in episodes are special. In episodes, an additional variable is available: episode. It contains the current episode object.

For example, you could build your own download list:

{% raw %}
<ul>
{% for file in episode.files %}
{% if file.asset.downloadable %}
<li>
<a href="{{ file.url }}">{{ file.asset.title }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
{% endraw %}

Shortcode Options

To make template modular and reusable, you can pass options to the template shortcode. They are then available under the option accessor. So a template embedded using [podlove-template template="episode" language="en"] will have access to the variable {{ option.language }}.

To set option defaults. Here is an example:

{% raw %}
{# call shortcode with, for example, size="small" parameter, or let it default to "big-logo" #}

{% set option = {
size: 'big-logo',
colors: 'black;;;#ffffff'
}|merge(option) %}

{{ podcast.subscribeButton({colors: option.colors, size: option.size}) }}
{% endraw %}

Subtemplates

If you are looking for a way to reuse template parts or want to split up complex templates, subtemplates are the solution. They allow to embed templates in templates while keeping the scope of one local variable. All global variables are available as usual.

An example:

The template file-link contains the markup to render the link to a file.

{% raw %}
<a href="{{ file.url }}">{{ file.asset.title }}</a>
{% endraw %}

Now this template can be used in another template. All variables from the parent template are available in the child template.

{% raw %}
<ul>
{% for file in episode.files %}
{% if file.asset.downloadable %}
<li>{{ include("file-link") }}</li>
{% endif %}
{% endfor %}
</ul>
{% endraw %}

Macros

Twig allows you to create macros to put often used HTML idioms into reusable elements to not repeat yourself. To be able to use them in multiple templates, they are best saved in a separate template. You might call it "mymacros":

{% raw %}
<!-- template "mymacros" -->
{% macro input(name, value, type, size) %}
<input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" />
{% endmacro %}
{% endraw %}

To use them in another template, you need to import the macros before using them:

{% raw %}
{% import "mymacros" as forms %}
{{ forms.input('username') }}
{% endraw %}

Filters

Twig filters can be used to filter the list of episodes. For example, this filter selects only the episodes from the year 2024:

{% set filtered_episodes = podcast.episodes|filter(episode => episode.publicationDate.format('Y') == "2024") %}

<ul>
{% for episode in filtered_episodes %}
<li>
<a href="{{ episode.url }}">
{{ episode.title }}
</a>{{ episode.subtitle }}
</li>
{% endfor %}
</ul>

More Examples

Additional template examples are available in the Templates reference page

Episode Page and RSS Feed: Automatic Template Insertion

In Podlove Publisher, templates can be automatically inserted into episode content. This setting is managed in the WordPress admin interface under wp-admin/admin.php?page=podlove_templates_settings_handle. Here, you can specify which templates should be automatically included in your episode pages. In the screenshot below, the template named default in automatically inserted.

Default Template Behavior

By default, the default template is applied to all episodes. This template's content will be displayed on the episode's HTML page and embedded within the <content:encoded><![CDATA[ ... ]]></content:encoded> tag in the RSS feed.

Web Player Insertion

The default template includes the web player for the episode. To ensure that the web player does not appear in the RSS feed, the template uses the following Twig condition:

{% if not is_feed() %}

This ensures that the player is only displayed on the WordPress site and not in the feed.

Feed-Specific Content

If you need to include content exclusively for podcast clients and not for the WordPress site, you can use {% if is_feed() %}. For example, to provide the episode's URL to podcast clients, you can use:

{% if is_feed() %}
{{ episode.url }}
{% else %}
...
{% endif %}

These functionalities allow you to customize the presentation and behavior of your podcast content, for both website visitors and podcast listeners.

Read more about episode-specific template tags in the episode reference page.

Creating PHP Templates — For Theme Developers

Available from Podlove Publisher version 2.3

You have access to the complete Podlove Publisher template system from PHP, which is ideal for creating themes.

The template variables and API is identical to the one provided by Twig. Just the syntax is different.

{% raw %}
<ul>
{% for episode in podcast.episodes %}
<li>{{ episode.title }}</li>
{% endfor %}
</ul>
{% endraw %}

is equivalent to

<ul>
<?php foreach (\Podlove\get_podcast()->episodes() as $episode): ?>
<li><?php echo $episode->title() ?></li>
<?php endforeach ?>
</ul>

API Entry Points

There are currently 4 entry points to the API: through the podcast, episode or network.

Podcast

<?php
/**
* Get Podlove podcast template object.
*
* @param int $blog_id Optional. Blog ID. Defaults to global $blog_id.
* @return \Podlove\Template\Podcast
*/
function \Podlove\get_podcast($blog_id = null);

// example
$podcast = \Podlove\get_podcast();
echo $podcast->title();
?>

Episode

<?php
/**
* Get Podlove episode template object.
*
* @param int|WP_Post $post Optional. Post ID or post object. Defaults to global $post.
* @return \Podlove\Template\Episode
*/
function \Podlove\get_episode($id = null);

// example
$episode = \Podlove\get_episode();
echo $episode->player(['context' => 'episode']);
?>

Network

<?php
/**
* Get Podlove network template object.
*
* Only available in WordPress Multisite environments.
*
* @return \Podlove\Modules\Networks\Template\Network
*/
function \Podlove\get_network();

// example
$network_lists = \Podlove\get_network()->lists();
?>

Hint: Short syntax for PHP 5.6+

If you develop a theme for PHP 5.6+ environments, you may want to use function importing for a nicer syntax, like that:

<?php
// once at the beginning of each file, ONLY PHP 5.6+
use function \Podlove\get_episode;
use function \Podlove\get_podcast;

echo get_podcast()->title();
?>