Header
The header template defines the primary site navigation, rendered at the top of every page.
The header template defines the primary site navigation, rendered at the top of every page. Creators manage navigation
items in My Site > Header or directly from any site page. The template code lives at partials/menu/index.html.
The terms "header" and "menu" are used interchangeably. In the site builder, creators see "Header". In theme code,
the template is in the menu folder and the Liquid object is called menu.
Location
The header template is located at:
partials
└── menu
└── index.htmlThe header is a special kind of partial - unlike regular partials, it
is automatically rendered at the start of the <body> tag on every page. You don't need to include it manually.
Schema
The header template supports a schema defined in YAML front matter, just like blocks. The schema defines both the navigation configuration and any custom variables that creators can set.
Navigation settings
The following front matter keys control navigation behaviour:
| Key | Type | Default | Description |
|---|---|---|---|
max_item_levels | integer (1–3) | 1 | The maximum depth of nested navigation items. Set to 2 or 3 to allow dropdown/sub-navigation in the site builder. |
supports_open_new_tab | boolean | false | When true, creators can toggle "Open in a new tab" on individual navigation items. |
cache | boolean | true | Controls whether the header is cached. Set to false for dynamic content like cart item counts. |
Custom variables
Any variables defined in the attributes block are accessible
on the menu object using dot notation:
---
max_item_levels: 2
supports_open_new_tab: true
cache: false
attributes:
background_colour:
type: color
label: Background colour
logo:
type: image
label: Logo
cta_text:
type: string
label: CTA button text
cta_link:
type: link
label: CTA button link
---<header style="background-color: {{ menu.background_colour }};">
{% if menu.logo %}
<img src="{{ menu.logo.url }}" alt="{{ menu.logo.alt }}">
{% endif %}
{% if menu.cta_text and menu.cta_link %}
<a href="{{ menu.cta_link.url }}">{{ menu.cta_text }}</a>
{% endif %}
</header>The menu object
The menu Liquid object is available inside the header template. It exposes:
| Property | Type | Description |
|---|---|---|
items | array | The top-level navigation items, sorted by position. Each item may contain nested items. |
| (custom attributes) | varies | Any variable defined in the schema — accessed via menu.variable_name. |
Navigation items
Each item in menu.items exposes the following properties:
| Property | Type | Description |
|---|---|---|
label | string | The display text for the navigation item. |
url | string | The resolved URL. Blank for folder items. |
new_tab | boolean | Whether the link should open in a new tab. Only configurable by creators when supports_open_new_tab is true. |
items | array | Child navigation items. Empty if the item has no children. |
linked_resource | drop | The linked page, product, or blog post object (as a Liquid drop). nil for external links and folders. |
Folder items have a blank
url— they exist only as parent containers for child items. In your template, render them as non-clickable labels or toggle buttons rather than links.
Template context
In addition to the menu object, the header template has access to the following objects:
| Object | Description |
|---|---|
company | The current company. |
cart | The current shopping cart. |
user | The currently logged-in user, if any. |
page | The current HTTP request (path, URL, host, params, locale). |
search | The search object. |
Rendering navigation
Basic navigation
The essential code to render a 2-level navigation:
---
max_item_levels: 2
supports_open_new_tab: true
---<nav>
{% for item in menu.items %}
<a href="{% if item.url != '' %}{{ item.url }}{% else %}javascript:void(0);{% endif %}"
{% if item.new_tab %}target="_blank" rel="noopener noreferrer"{% endif %}>
{{ item.label }}
</a>
{% if item.items.size > 0 %}
<ul>
{% for nested_item in item.items %}
<li>
<a href="{% if nested_item.url != '' %}{{ nested_item.url }}{% else %}javascript:void(0);{% endif %}"
{% if nested_item.new_tab %}target="_blank" rel="noopener noreferrer"{% endif %}>
{{ nested_item.label }}
</a>
</li>
{% endfor %}
</ul>
{% endif %}
{% endfor %}
</nav>Handling folder items
Folder items have no URL and act as parent containers. You can detect them by checking for a blank url:
{% for item in menu.items %}
{% if item.url != '' %}
<a href="{{ item.url }}">{{ item.label }}</a>
{% else %}
<button type="button">{{ item.label }}</button>
{% endif %}
{% endfor %}Using linked_resource
The linked_resource property gives you access to the full Liquid drop for the linked page, product, or blog post. This is useful for displaying additional information beyond the label:
{% for item in menu.items %}
{% if item.linked_resource %}
<a href="{{ item.url }}">
{{ item.label }}
{% if item.linked_resource.type == 'experience' %}
<span>from {{ item.linked_resource.display_price }}</span>
{% endif %}
</a>
{% endif %}
{% endfor %}Caching
By default, the header template is cached so it renders quickly. The cached version is served for all requests until the cache is invalidated (e.g. when the header content or settings are updated).
Dynamic content
If your header needs content that changes per request — such as a cart item count or user-specific greeting — set cache: false
in the front matter:
---
cache: false
---With caching disabled, the entire header is rendered on every request. To maintain performance, wrap the static parts of your
header (logo, navigation links, CTA buttons) in a cache tag:
{% cache menu %}
<div class="header__logo">
<img src="{{ menu.logo.url }}" alt="{{ menu.logo.alt }}">
</div>
<nav>
{% for item in menu.items %}
<a href="{{ item.url }}">{{ item.label }}</a>
{% endfor %}
</nav>
{% endcache %}
<div class="header__cart">
<span>{{ cart.total_items }}</span>
</div>This approach gives you the best of both worlds: static content is cached for performance, while dynamic content is rendered fresh on every request.
Hiding the header
The header can be hidden entirely for specific use cases (e.g. landing pages or checkout flows). When hidden, the header template is not rendered and no HTML is output. This is controlled at the platform level, not in the theme template.