Power Pages Liquid templating
By Emil Björk · Microsoft business apps consultant, Gothenburg
How Liquid templates work in Power Pages — variables, tags, filters, rendering Dataverse data, and the design patterns for customer-facing portals.
On this page (7)
Power Pages portals — Microsoft's external-facing website platform on top of Dataverse — render content through the Liquid template language. Originally created by Shopify, Liquid is a logic-light templating language designed for safe content rendering. Understanding it is essential for building anything beyond the simplest Power Pages portal.
The Liquid concept
Liquid templates mix HTML with objects (data variables), tags (control flow), and filters (transformations). Templates compile and render server-side; the result is HTML sent to the user's browser.
Three types of Liquid elements.
- Output (in
{{ }}) — print a value. - Tags (in
{% %}) — control flow (if, for, capture, etc.), but no output. - Filters (in
| filter) — transform values during output.
Example:
{% if user.fullname %}
<p>Welcome, {{ user.fullname | upcase }}!</p>
{% else %}
<p>Welcome, guest.</p>
{% endif %}
The {% if %} and {% endif %} are tags; {{ user.fullname }} is an output; | upcase is a filter.
Power Pages-specific objects
The portal exposes specific objects:
user— the authenticated user (when signed in). Properties includefullname,email,id,roles.page— the current page being rendered. Properties:title,summary,url.entities— access to Dataverse entities. Used for querying records:{% entitylist logical_name:"contact" %}.entityform— for forms tied to specific Dataverse forms.weblinks— navigation menus configured in Power Pages.request— current HTTP request context.settings— site-level configuration.now— current date/time.
These objects give templates access to the live data layer of the portal.
Querying Dataverse records.
{% fetchxml entities_query %}
<fetch>
<entity name="opportunity">
<attribute name="name" />
<attribute name="estimatedvalue" />
<filter>
<condition attribute="ownerid" operator="eq" value="{{ user.id }}" />
</filter>
</entity>
</fetch>
{% endfetchxml %}
{% for opp in entities_query.results.entities %}
<p>{{ opp.name }} — {{ opp.estimatedvalue | currency }}</p>
{% endfor %}
The {% fetchxml %} tag runs a FetchXML query; the result is available in subsequent template logic. Power Pages also supports the {% entityview %} tag for using saved Dataverse views and {% entitylist %} for configured lists.
Common filters.
upcase,downcase,capitalize— case manipulation.date— format dates ({{ contact.createdon | date: "yyyy-MM-dd" }}).currency— format money values.escape— HTML-escape (default for user content; rarely turned off).size— count of array or characters of string.firstandlast— first / last element of an array.limit— limit array to N elements.truncate— shorten text.replace— string replace.url_encode— for building safe URLs.
Logic — if, unless, case.
{% if user.roles contains 'VIP' %}
<p>VIP content</p>
{% elsif user.roles contains 'Member' %}
<p>Member content</p>
{% else %}
<p>Public content</p>
{% endif %}
{% case user.country %}
{% when "Sweden" %}
<p>Welkommen!</p>
{% when "Germany" %}
<p>Willkommen!</p>
{% else %}
<p>Welcome!</p>
{% endcase %}
Loops — for.
{% for opportunity in opportunities %}
<p>{{ opportunity.name }}</p>
{% endfor %}
{% for product in products limit: 5 %}
<p>{{ product.name }}</p>
{% endfor %}
Capture and variables
{% capture %} stores rendered output in a variable for later use:
{% capture greeting %}
Hello, {{ user.fullname | default: "guest" }}
{% endcapture %}
<h1>{{ greeting }}</h1>
Includes
Reusable template fragments via {% include %}:
{% include 'header' %}
... main content ...
{% include 'footer' %}
Performance
Liquid is fast but complex queries inside loops can degrade:
- Move queries outside loops where possible.
- Use
{% fetchxml %}with precise filters rather than fetching everything. - Cache repeated lookups in
capturevariables.
Security
Liquid is sandboxed — templates can't execute arbitrary code; they can only call defined functions and access defined data. This is the deliberate safety property — templates run as content, not as code.
User-supplied input rendered through Liquid is escaped by default (HTML-escaped), preventing XSS. Don't bypass escaping unless you know the source is trusted.
Common pitfalls.
- Queries inside heavy loops — N+1 query pattern slows rendering.
- Forgetting to escape — using
| rawor similar to bypass escaping on user content is an XSS vulnerability. - Templates that mix too much logic — Liquid is for presentation; complex business logic belongs in Power Automate / plug-ins, not templates.
- Unfamiliar filter / tag — Microsoft documents Power Pages-specific extensions; verify exists before using.
Operational reality
Liquid is straightforward once you've built a few templates. The Power Pages designer + Liquid combination produces effective portals without diving into full web development. For more complex needs (rich client interaction, custom UI), consider whether Power Pages is the right tool or if a custom-built solution makes more sense.
Further reading
Related guides
- Power Pages for Dynamics 365 customer portalsBuilding customer-facing portals on top of Dataverse — Power Pages templates, authentication, security, and operational realities.
- Power Pages security, in depthHow Power Pages secures external-facing portals — identity providers, web roles, table permissions, page permissions, and the audit and DLP that wraps them.
- Power Pages with Dataverse searchHow to make Power Pages portals searchable — enabling Dataverse search, scoping by table and security, indexing, and the patterns for portal-friendly search UX.
- Power Pages Liquid and portal errorsThe Power Pages errors makers hit most — Liquid syntax and permission errors, form submission failures, and the ones that only show up in production.
- Power Apps model-driven form errorsWhy a Dataverse model-driven form won't save, a business process flow gets stuck, or a form control shows the wrong data — decoded.
Browse every guide in Power Platform or just Power Pages.
Was this helpful?
Signals which guides land and which need work. No account, no comment box — corrections go through the contact page.
Spot something wrong or want a topic covered? Send a correction or a topic request — both are welcome.