Post Loop Widget

The Post Loop Widget displays posts using available theme templates. The Query Builder can filter your posts using a wide array of parameters.

Optionally insert a widget title.

Choose a theme template to display your posts. The Post Loop Widget looks for templates within your theme with the following file names:


SiteOrigin themes like Corp have loop templates available for the Post Loop Widget. If your theme doesn’t offer predefined templates, you can try using one of the content partials if those are available in the drop-down list.

More Link
If the template supports it, cut posts and display the more link.

Posts Query

Post Type
Choose between All, Posts, Pages, or any other available post types in your WordPress installation.

Post In
Specify posts to retrieve. Click on the field and use the provided search field to search for your post or browse the abbreviated list under the search field.

Specify taxonomies to retrieve. Taxonomies are groups such as categories, tags, posts, and products. Click on the field and use the provided search field to search for your taxonomies or browse the abbreviated list under the search field.

Taxonomies Relationship
The relationship between taxonomies. Choose between OR or AND. OR requires posts to have at least one of the specified taxonomies. AND requires posts to have all of the specified taxonomies.

Date Selection Type
Choose between specific or relative.
Select a range between specific dates or relative to the current date.

Select a from and to date.

Order By
Choose how to order your posts. The following options are available:

  • No order
  • Post ID
  • Author
  • Title
  • Published date
  • Modified date
  • By parent
  • Random order
  • Comment count
  • Menu order
  • By meta value
  • By numerical meta value
  • By include order

Order Direction
Choose between Ascending or Descending.

Posts Per Page
Optionally enter the number of posts to display per page. If a value isn’t entered, this setting will fallback on the global setting at SettingsReading.

Sticky Posts
Choose between Default, Ignore sticky, Exclude sticky, and Only sticky.

Default: Sticky posts are displayed at the top of the post loop. If an offset is applied via the Additional field, it won’t be applied to the sticky posts. This is the WordPress default behavior.

Ignore sticky: Sticky posts won’t be moved to the top of the post loop but will still be displayed in their normal published position.

Exclude: All sticky posts will be excluded from the post loop.

Only sticky: Only sticky posts will be displayed. All other posts will be removed.

Additional query arguments. See query_posts.

Below you’ll find a few examples of additional query arguments you might use.

Don’t Display the Most Recently Published Post:

* If Posts per page is set to -1 offset is ignored.
* If you have any sticky posts present offset won’t work 100% as expected, the Post Loop Widget will count the sticky posts as offset but still output them so it’ll appear as though nothing changed. Set Sticky posts to Ignore sticky to remove sticky posts from the loop.

Advanced Customizations

Adding Loop Templates to Your Child Theme or Custom Plugin

Child Theme

You can overwrite existing theme loops or add new loops within a child theme.

To overwrite an existing theme loop, make a copy of the loop file and paste it into your child theme. The loop file must be stored in the same relative location and keep the same file name if you’d like to overwrite the copy in the parent theme. For example, if in our SiteOrigin North theme you’d like to overwrite the loops/loop-blog.php file, in your child theme create a loops folder and insert a copy of the loop-blog.php file into the child theme loops folder.

Adding a new theme loop to a child theme requires the loop file to have one of the following naming conventions:


Where * can be any name. loop-grid.php for example. Loop files can be inserted anywhere in your child theme.

Custom Plugin

Within your custom plugin, begin by letting Page Builder know which directory you’ll be storing your post loop templates in. If you haven’t yet created that directory, do so now. In our example, we’re naming the directory loops.

function so_custom_postloop_directories( $directories ) {
	$directories[] = plugin_dir_path( __FILE__ ) . '/loops/';

	return $directories;
add_filter( 'siteorigin_panels_postloop_template_directory', 'so_custom_postloop_directories' );

Next, create your loop templates in the newly created directory and then use the function below to register each loop template.

function so_custom_postloop_templates( $templates ) {
	$templates[] = 'so-custom-post-loop/loops/loop-plugin.php';

	return $templates;
add_filter( 'siteorigin_panels_postloop_templates', 'so_custom_postloop_templates' );

Note the template path begins with the plugin directory name.
Repeat $templates[] = 'so-custom-post-loop/loops/loop-plugin.php'; for each loop template that you’d like to add.

Download an example plugin.

Custom Pagination

If you’d like to use more than one Post Loop Widget with pagination on a page, it’s necessary to add custom pagination to your templates to ensure that each Post Loop Widget paginates independently. If you have two Post Loop Widgets on a page, only one of the widget templates will need to use custom pagination.

echo paginate_links( array(
	'format'    => '?page-' . SiteOrigin_Panels_Widgets_PostLoop::get_current_pagination_id() . '=%#%',
	'prev_next' => false,
) );

Changing the Taxonomy Field from OR to AND

By default, the Taxonomies field uses a relationship of OR. To change the behavior of the Taxonomies field to AND, you can use the following function. This is useful if you’d like to list posts only if they are included in multiple categories. For example, only display posts if they are within category A and category B.

function so_posts_selector_and_relation( $query ) {
    if ( isset( $query['tax_query'] ) ) {
        $query['tax_query']['relation'] = 'AND';
    return $query;
add_filter( 'siteorigin_widgets_posts_selector_query', 'so_posts_selector_and_relation' );

Filtering Example: Excluding a Category from a Post Type Loop

In this example, we’ve created an events post type, and within that post type, a category for past events. We’d like to remove all past events from the main events page. We’re displaying events on the events page using a Post Loop Widget.

 * Filter the SiteOrigin Widget Post Loop.
function so_posts_query_exclude_term( $query ) {
	$terms = array(
		'taxonomy' => 'event_categories', // This is the taxonomy name.
		'field'    => 'term_id',
		'terms'    => 1625, // Term to exclude.
		'operator' => 'NOT IN'

	// Is there a taxonomy query already present?
	if ( is_page( 59427 ) ) {
		return $query;
	} elseif ( isset( $query['tax_query'] ) ) {
		$query['tax_query'][] = $terms;
		$query['tax_query']['relation'] = 'AND';
	} else {
		$query['tax_query'][] = $terms;

	return $query;
add_filter( 'siteorigin_widgets_posts_selector_query', 'so_posts_query_exclude_term' );

In the above example, 1625 is the category ID for Past Events that we’d like to exclude from the main events page. 59427 is the category page for Past Events. We’re returning early on the Past Events category page as there isn’t any need to run this filter.

Getting the Current Loop Template

You can check what template the user has selected by using SiteOrigin_Panels_Widgets_PostLoop::get_current_loop_template(). This method will always return the current template as a string. For example, the following snippet will alter the tax_query relation if a taxonomy is set and if the current template is loops/grid.php.

 * Set the tax_query relation to AND if the current template is loops/grid.php.
function so_posts_selector_alter_tax_relation_template( $query ) {
	if (
		method_exists( 'SiteOrigin_Panels_Widgets_PostLoop', 'get_current_loop_template' ) &&
		isset( $query['tax_query'] )
	) {
		// Check if currently active template is loops/grid.php.
		if ( SiteOrigin_Panels_Widgets_PostLoop::get_current_loop_template() == 'loops/grid.php' ) {
				$query['tax_query']['relation'] = 'AND';

	return $query;
add_filter( 'siteorigin_widgets_posts_selector_query', 'so_posts_selector_alter_tax_relation_template' );

The above example won’t work unless the Post Loop Widget has access to loops/grid.php. For testing purposes, you should change it to a different template.

Getting The Post Loop Instance In The Template

It’s possible to get the current post loop instance while the template is rendering by using SiteOrigin_Panels_Widgets_PostLoop::get_current_loop_instance(). That will return an array of the post loop instance. This will allow you to modify the template based on the values the user selects.

Get The Most Out of SiteOrigin with SiteOrigin Premium

Find Out More