As our user count has been steadily growing, the last few releases of Loops & Logic have focused on resolving bugs and extending the existing functionality of the plugin to support as many flexible and niche use cases as possible. With the launch of version 3.2.0, we’re getting back to the exciting stuff: new features! Let’s take a look at what’s new.

The big picture

Here’s a highlight of the features we’re most excited about that have been released with versions 3.2.0 to 3.2.9:

The layout template type now allows inserting headers and footers

Loops & Logic is an incredibly flexible tool and, when used right, can act as a replacement for lots of other single-use plugins. The layout template type has always allowed using L&L as a lightweight theme tool thanks to its ability to insert or replace parts of a theme with L&L templates.

Version 3.2.0 introduces two new theme positions: “Document Head” and “Document Foot.” These new location options enable inserting content into the <head> tag or just above the closing </body> tag on any page, making it easy to insert marketing scripts or even dynamic page meta without needing to install a single-purpose headers and footers plugin.

The document head theme position can be useful for adding dynamic meta tags, JSON-LD schema, or link tags to load CSS files. The document foot position can be used to add script tags to load JavaScript files.

Easily add dynamic schema using the new JSON-LD tag

Structured data, or microdata, is a helpful method of organizing information about a web page in a way that’s readable by both humans and machines. One of the most significant initiatives related to structured data is, a set of guidelines that can be used to categorize specific types of data on the web. This data can then be used by search engines to understand information about the page and display it more easily to users. For example, if you have an FAQ page, you could add your questions and answers as structured data to increase the likelihood that your site will be featured in the “related questions” section of Google’s search engine results page.

The recommended format for this data is called JSON-LD, but this format can be cumbersome to write and difficult to generate dynamically.

Luckily, version 3.2.0 includes a new JSON-LD tag that accepts data in exactly the same way as the existing Map tag, but enables converting content from your site into JSON-LD markup.

For example, if your site had a custom post type dedicated to frequently asked questions, you might dynamically generate some schema for your FAQ using a template like the one shown below.

    <Key type value=FAQPage />
    <List mainEntity>
      <Loop type=support count=5>
          <Key type value="Question" />
          <Key name value="{Field title}" />
          <Map acceptedAnswer>
            <Key type value="Answer" />
            <Key text value="{Field content}" />

This template uses the exact same structure as traditional JSON-LD markup but uses the familiar Key, List, and Map tags to create key-value pairs, arrays, and associative arrays. These tags are much simpler to work with dynamically in the L&L language compared to the brackets and braces of traditional JSON.

To output the results of this JSON-LD tag as schema, use the new “Document Head” theme position mentioned above.

The incredibly flexible tag-attributes attribute now works with dynamic tags too

In version 3.0.0, we introduced a new flexible attribute that could be used on any HTML tag called tag-attributes. If you haven’t already tried it out for yourself, it essentially renders anything written in its value as attributes of the current tag. For example, if you wanted to have an audio file on your page that played automatically for logged-in users, your template might look something like this:

    <audio src="music.mp3" tag-attributes="{If user}autoplay{/If}"></audio>

This was initially implemented to work specifically with HTML tags since boolean tags in HTML don’t accept a value and are simply true or false based on whether they exist on the tag. In contrast, all the boolean attributes in the L&L language accept a value of either true or false, which makes the much easier to work with dynamically since you can simply set a dynamic value using regular L&L syntax, like this: some_attribute="{If some_condition}true{Else /}false{/If}".

While boolean attributes are already easy to work with in L&L, there are some occasions where it may be useful to dynamically add or modify several L&L attributes all at once. To make this possible, we’ve now extended the tag-attributes attribute to work with dynamic tags as well as static tags.

Better support for sticky posts in the Loop tag

Since WordPress was first released two decades ago, it’s undergone an incredible transformation. Starting as a simple blogging platform, it now supports just about any data structure and functionality imaginable. Unfortunately, that means WordPress still has a few relics of its blog-centric past.

Case in point: sticky posts. As its name suggests, this feature was added to WordPress as a way to “stick” specific posts to the top of a blog. Unfortunately, since this feature was implemented back when a blog’s home page was almost always its main post archive, there are some weird oversights in the way it’s currently implemented. Namely sticky posts generally don’t work unless $query->is_home is true. In other words, WordPress officially only supports sticky posts on a site’s home page.

While Loops & Logic was initially built to mirror how WordPress natively handles sticky posts, you’ll agree that it’s time WordPress gave sensible options for working with sticky posts. While those might not exist in core, version 3.2.0 of L&L now includes more flexible ways of working with sticky posts in the Loop tag.

The new sticky query parameter of the Loop tag provides more options to work with sticky posts in a loop. It accepts three possible values:

  • sticky=true puts sticky posts at the beginning of the loop
  • sticky=false excludes sticky posts from the loop altogether
  • sticky=only loops through only sticky posts and ignores non-sticky posts

If the sticky query parameter isn’t set, the loop simply ignores whether a post is sticky or not and loops through posts as usual.

The Url tag includes more support for query parameters

The Url tag is a longstanding tag that allows dynamically rendering a URL, whether that’s for the current page or some other page on the site. One feature that hadn’t been well-supported until now was the ability to reference the current URL along with all its parameters.

In 3.2.0, the new query=true attribute allows referencing the current URL along with all its query parameters. This attribute can also be used in conjunction with the include and exclude attributes to selectively pass query parameters by name. These two attributes accept a comma-separated list to reference multiple names.

A new remove_html attribute strips HTML markup with the Format tag

As of version 3.2.1, the Format tag now includes a remove_html attribute that, as its name suggests, removes all HTML tags and attributes contained within it. For example, the template below includes several HTML tags along with some Javascript contained within a script tag. By wrapping this in the Format tag, it’s now possible to remove this data and be left with just the text data. In the example below, the output of the template would be 12345.

  <Format remove_html>
    <a href="">123</a><script>alert("hi")</script><b>456</b>

A new post_type query parameter allows you to future-proof your post loops

Up until version 3.2.3, the main way of looping through a custom post type on your site involved passing the name of your custom post type to the type query parameter.

  <Loop type=my_custom_post_type count=3>
    <p><Field title /></p>

The type parameter has always been used to specify the loop type and in cases where its value didn’t refer to an existing loop type, it would instead assume that its value referred to a custom post type. This was a helpful way of keeping templates compact, but it also resulted in a potential issue. If ever a site included a custom post type with the same name as one of L&L’s loop types (such as a CPT called taxonomy_term or user), there would be no way to loop through posts from that post type. This hasn’t caused any issues for users as far as our team is aware, but as we introduce more and more loop types, the potential for collisions and conflicts would have increased.

To improve the flexibility of the post loop, version 3.2.3 introduces a new recommended way to refer to a post type using the new post_type query parameter.

  <Loop type=post post_type=my_custom_post_type count=3>
    <p><Field title /></p>

By using this post_type parameter, you can ensure that even as more loop types continue to be added in the future, you’ll always be able to refer to your custom post types in your templates.

To keep the syntax compact, there is also a new shorthand syntax. When a loop uses the post_type parameter, L&L understands that the loop is a post loop and it’s not necessary to specify the loop type using type=post.

  <Loop post_type=my_custom_post_type count=3>
    <p><Field title /></p>

This is already a convention among the other loop types, such as the taxonomy term loop which can be written in full as <Loop type=taxonomy_term taxonomy=category> or can be written using the shorthand syntax, <Loop taxonomy=category>.

Note that this change to the post loop is backward compatible and all templates that use the type parameter’s value to refer to a custom post type will continue to work as expected. However, to ensure that your template works in the long term and to avoid issues with any loop types that may be added in the future, it’s recommended that the post_type parameter be used instead.

Powerful new ways to format strings

L&L’s Format tag has always included some surprisingly useful formatting options, but it fell short compared to other languages when it came to modifying strings. Version 3.2.8 of the plugin shook things up, adding a ton of new ways to format content, including super flexible regex options.

Below is an overview of the new attributes that can be used with the Format tag. For a more thorough description of these attributes along with examples, take a look at the Format tag’s documentation.

  • split – Split a string into a list based on a particular character.
  • list – Apply a given format to every item in a list.
  • index – Return the nth character of a string or the item of a list.
  • offset – Return the part of a string after the nth character of a string or item of a list.
  • length – Limit the maximum length of characters in a string or items in a list.
  • words – Limit the maximum length of words in a string.
  • split – Split a string into a list using a delimiter character.
  • join – Join a list into a string using a delimiter character.
  • trim_left, trim_right, and trim – Trim (remove) whitespace or other characters from the beginning, the end, or both ends of a string.
  • prefix and suffix – Add a string before or after a string or each item in a list.
  • reverse – Reverse the order of characters in a string or items in a list.
  • replace_pattern – Replace a string matching a regular expression with another string.
  • match_pattern – Return a list of strings that match a regular expression.

Full changelogs from versions 3.2.0 to 3.2.9


  • Format tag
    • Format list index: Fix warning from array_shift()
    • Support capture groups for replace_pattern, for example: replace_pattern=”/(\d{3})/” with=”$1″
    • When invalid regular expression is passed, emit a warning instead of throwing an error


  • Date module: Upgrade Carbon date library to version 2.68.1 with better PHP 8.x compatibility
  • Format tag
    • Add list and string format methods
    • index, offset, length, words – Cut a piece of string by position
    • split, join – Split string to list, and back
    • trim, trim_left, trim_right – Remove whitespace or given characters from start/end
    • prefix, suffix – Add string before or after
    • reverse – Reverse a string or list
    • Regular expressions – replace_pattern, match_pattern
    • Multibyte string: uppercase, lowercase, capital, capital_words
    • Format list
    • Format every item in a list
    • Nested list formats
  • If tag
    • Add comparison “matches_pattern” to match value to regular expression
    • Improve comparison “includes” to support a List loop instance, for example: <If acf_checkbox=field_name includes value=some_value>


Release Date: 2023-06-01

  • Link tags: Ensure any null is converted to empty string before passing to str_replace – Compatibility with PHP 8.x


Release Date: 2023-05-31

  • Beaver integration: Fix issue with BeaverBuilder 2.7 and above preventing control to be initialized in the editor
  • Controls: Add new alignment_matrix control


Release Date: 2023-05-27

  • Post loop
    • For loop types that inherit from post loop, such as attachment, ensure backward compatibility with deprecated query parameter “type”
  • Blocks
    • Define a “block” variable to access the current block information from the JavaScript context (builder, post_id, controls, universal_id, wrapper)
    • Set new blocks to new controls by default
  • Controls
    • Number: If defined, “min” attribute will be used as default if no value set
    • Editor: Switch from TinyMCE to ProseMirror – Can still use TinyMCE by adding editor=”tinymce”
    • Repeater: Block layout – Add support for bulk actions


Release Date: 2023-05-24

  • Elementor integration: Improve dynamic module loader by removing AJAX library from dependency list of Template Editor script
  • Post loop: Improve handling when called directly without “type” or “post_type” parameter


Release Date: 2023-05-18

  • Elementor integration: Enqueue dynamic module loader only when inside preview iframe
  • Gutenberg integration: Improve compatibility with WP 6.2.1 – Remove the do_shortcode filter workaround that was necessary in previous versions; See
  • List and Map tag
    • Add Item/Key tag attribute “type” for value type: number, boolean, list, map
    • Improve Item/Key tag to treat single List or Map inside as direct value, instead of converting it to string
  • Loop tag
    • Add attribute “post_type” as the recommended way to create a post loop with custom post type
      This makes it distinct from attribute “type”, which creates an instance of a loop type (such as “post” or “user”) and only falls back to post loop if there’s no loop type with the same name
    • Fix pagination issue when attribute “tag” is used


Release Date: 2023-05-08

  • Elementor integration: Ensure dynamic modules are activated inside preview iframe
  • Format tag: Add attribute “remove_html” to remove HTML and make plain text
  • Post loop: Improve sticky posts – Ensure “orderby” is only applied to non-sticky posts


Release Date: 2023-04-26

  • Add JSON-LD tag: Create a map and generate script tag for JSON Linked Data
  • Format tag
    • Add attributes “start_slash” and “end_slash” to add slash to URL or any string; Use “start_slash=false” and “end_slash=false” to remove slash; These can be combined in one tag
    • Improve support for replace/with text that includes HTML
  • HTML module: Improve “tag-attributes” feature to support dynamic tags
  • Layout template type
    • Add theme position “Document Head” for adding Meta tags, JSON-LD schema, or link tag to load CSS files
    • Add theme position “Document Foot” for adding script tag to load JavaScript files
  • Loop tag
    • Add attribute “sticky” for improved sticky posts support
    • Without sticky set, treat sticky posts as normal posts; this is the default behavior (backward compatible)
    • With sticky=true, put sticky posts at the top
    • With sticky=false, exclude sticky posts
    • With sticky=only, include sticky posts only
    • Deprecate “ignore_sticky_posts” due to WP_Query applying it only on home page
  • Query variable type: Support passing loop attributes via AJAX, such as for pagination
  • Url tag
    • Add attribute “query=true” to include all query parameters in current URL
    • Add attributes “include” and “exclude” to selectively pass query parameters by name; Accepts comma-separated list for multiple names

One Comment

Leave a Reply

Your email address will not be published. Required fields are marked *