> For the complete documentation index, see [llms.txt](https://docs.rafflex.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rafflex.io/advanced/twig-templating.md).

# Twig Templating

Twig is a simple templating language that lets you design your own sections with HTML while pulling in live information from your site, such as your competitions, winners and branding. Many page build

Twig lets you write your own HTML for a section of your site and drop live information into it. For example, you could build a hero banner that always shows your three competitions ending soonest, or a winners strip that updates itself every time someone wins.

You do not need to be a developer to use it, but you will be writing a little code. If you have edited HTML before, or you are happy to work alongside an AI assistant, you will be fine.

{% hint style="info" %}
**Not sure you need Twig?** Every block that offers Twig also has ready made layouts that need no code at all. Start with those (see [Page Builder Blocks](/customise-your-site/page-builder-blocks.md)) and only switch to Twig when you want a design the built in layouts cannot give you.
{% endhint %}

***

### Where Can I Use Twig? <a href="#where-can-i-use-twig" id="where-can-i-use-twig"></a>

There are two ways to use Twig in the page builder.

**1. The Custom Twig Block.** This is a block dedicated to Twig. You create your own variables (text, images, colours, competitions, recent winners, the logged in customer and more) and write a template to display them. It is the most flexible option.

{% content-ref url="/pages/0sIXHlxMUQHe7yheXOco" %}
[Custom Twig Block](/advanced/twig-templating/custom-twig-block.md)
{% endcontent-ref %}

**2. The "Custom Twig (Advanced)" layout on other blocks.** These blocks have a layout or style dropdown with a **Custom Twig (Advanced)** option. When you pick it, an extra section called **Custom Twig Code** appears. Click it to expand it, and write your template in the **HTML + Twig Code** editor. The Product grid is slightly different: its section is called **Custom Card Template**, and it has a **CSS Styles (loaded once)** editor for your styles and a **Card HTML + Twig Code** editor for the card itself. The block's own fields (such as its title and description) are passed into your template.

| Block (as named in the **Add to blocks** list) | Dropdown to change         | Information your template receives                                                                                                                                                    |
| ---------------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Sliders**                                    | **Slider Style**           | Your **Content** fields, the **Featured Image**, and every competition with **Add To Slider** switched on. See [Custom Twig Slider](/advanced/twig-templating/custom-twig-slider.md). |
| **Product grid**                               | **Competition Card Style** | One competition at a time, so you design a single card that is repeated for each competition. See [Custom Twig Product Grid](/advanced/twig-templating/custom-twig-product-grid.md).  |
| **Big picture content**                        | **Layout**                 | `title`, `description`, `button_text`, `button_url` and `image_url` (the image you uploaded to the block).                                                                            |
| **Call to action one**                         | **CTA Layout**             | `title`, `description`, `button_text` and `button_url`.                                                                                                                               |
| **Gallery**                                    | **Layout**                 | `title`, `description` and `gallery`, a list of your uploaded images. Each image has a `url` and a `name`.                                                                            |
| **Social links**                               | **Layout Style**           | `title`, `facebook`, `instagram`, `twitter` (the address you typed in the **X** field), `youtube` and `tiktok`.                                                                       |
| **Winners display**                            | **Winners Display Layout** | `title`, `description` and `gallery`, the winner photos you uploaded to the block. Each image has a `url` and a `name`.                                                               |
| **Instant Winners Counter**                    | **Layout Style**           | `winners_today`, the number of instant wins so far today.                                                                                                                             |

On top of each block's own information, every Twig template can also use your site's colours, logos, name, social links and review scores through the `settings` variable.

{% content-ref url="/pages/vB5jsxD96PEYyjaQvYL4" %}
[Settings Variables](/advanced/twig-templating/settings-variables.md)
{% endcontent-ref %}

{% hint style="info" %}
When you choose **Custom Twig (Advanced)**, the block's **Title**, **Description** and button fields stop being required. You can leave them empty and type your wording straight into the template instead, or fill them in and use them as variables. Using the fields makes it easier to change the wording later without touching the code.
{% endhint %}

If your site has a custom header or footer built by the RaffleX team, those templates use Twig too. See [Header and Footer Variables](/advanced/twig-templating/header-and-footer-variables.md) for what they can show.

***

### How to Switch a Block to Twig <a href="#how-to-switch-a-block-to-twig" id="how-to-switch-a-block-to-twig"></a>

{% stepper %}
{% step %}

#### Open the page

In the **admin panel**, look in the left hand menu under **Content** and click **Pages**. Click the page you want to change (for example your Home page).
{% endstep %}

{% step %}

#### Find or add the block

Scroll to the block you want to customise. To add a new one, click **Add to blocks** at the bottom of the **Blocks** area and choose it from the list.
{% endstep %}

{% step %}

#### Choose Custom Twig (Advanced)

Open the block's layout or style dropdown (see the table above for its name) and choose **Custom Twig (Advanced)**.
{% endstep %}

{% step %}

#### Write your template

Click the **Custom Twig Code** section to expand it (on the Product grid it is called **Custom Card Template**). Type or paste your template into the **HTML + Twig Code** editor (**Card HTML + Twig Code** on the Product grid). The **Help** box underneath lists the variables this block gives you, with a **View Full Documentation** link back to these pages.
{% endstep %}

{% step %}

#### Save and check

Click **Save**, then open the page on your live site in a new tab and refresh it.
{% endstep %}
{% endstepper %}

{% hint style="warning" %}
**Check your page while logged in as an admin.** If your template has a mistake, admins see a red **Template Error** box on the live page that explains what went wrong. Your customers do not see that message. Instead, the section shows to them with your Twig code visible as plain text (for example `{{ product.title }}`), so fix any error straight away.
{% endhint %}

***

### Basic Syntax <a href="#basic-syntax" id="basic-syntax"></a>

Twig only has a few building blocks. Everything else in your template is ordinary HTML.

* `{{ ... }}` **prints** something onto the page.
* `{% ... %}` **does** something, such as making a decision or repeating a section.
* `{# ... #}` is a **comment**. It is ignored, so use it to leave yourself notes.

#### Display a Variable <a href="#display-a-variable" id="display-a-variable"></a>

```twig
<h1>{{ title }}</h1>
```

To show a value that sits inside another one (such as a field on a competition), use a full stop:

```twig
<h3>{{ product.title }}</h3>
<p>{{ settings.site_name }}</p>
```

#### Conditional (if/else) <a href="#conditional-ifelse" id="conditional-ifelse"></a>

Show something only when a condition is true:

```twig
{% if show_banner %}
  <div>Banner content here</div>
{% endif %}
```

Choose between options:

```twig
{% if product.is_sold_out %}
  <span>Sold out</span>
{% elseif product.percent_sold > 80 %}
  <span>Almost gone!</span>
{% else %}
  <span>Tickets available</span>
{% endif %}
```

You can combine conditions with `and`, `or` and `not`, and compare values with `==`, `!=`, `>`, `<`, `>=` and `<=`.

#### Loop Through Items <a href="#loop-through-items" id="loop-through-items"></a>

Repeat a section for every item in a list. The `{% else %}` part is optional and shows when the list is empty.

```twig
{% for product in products %}
  <h3>{{ product.title }}</h3>
{% else %}
  <p>New competitions are coming soon.</p>
{% endfor %}
```

Inside a loop, `loop.index` gives the position (starting at 1), and `loop.first` and `loop.last` tell you whether you are on the first or last item.

```twig
{% for winner in recent_winners %}
  <p>#{{ loop.index }} {{ winner.name }}</p>
{% endfor %}
```

#### Store a Value <a href="#store-a-value" id="store-a-value"></a>

Use `set` to save a value and reuse it:

```twig
{% set accent = settings.primary_color %}
<h2 style="color: {{ accent }};">{{ title }}</h2>
```

#### Use a Filter <a href="#use-a-filter" id="use-a-filter"></a>

A filter changes a value before it is shown. Add it after a `|` (the vertical bar key):

```twig
{{ name|upper }}
{{ subtitle|default('No subtitle') }}
{{ product.percent_sold|round }}%
```

***

### What Twig Can Do Here <a href="#what-twig-can-do-here" id="what-twig-can-do-here"></a>

To keep your site fast and secure, templates support a focused set of Twig features. Anything not listed here shows a **Template Error** for admins.

**Tags:** `if` (with `elseif` and `else`), `for` (with `else`) and `set`.

**Filters:**

| Filter          | What it does                                        | Example                                      | Result                                          |
| --------------- | --------------------------------------------------- | -------------------------------------------- | ----------------------------------------------- |
| `upper`         | Capital letters                                     | `{{ 'win big'\|upper }}`                     | WIN BIG                                         |
| `lower`         | Small letters                                       | `{{ 'WIN BIG'\|lower }}`                     | win big                                         |
| `default`       | A fallback when the value is empty                  | `{{ subtitle\|default('Enter now') }}`       | Enter now (if there is no subtitle)             |
| `length`        | How many items are in a list, or characters in text | `{{ products\|length }}`                     | 6                                               |
| `first`         | The first item in a list                            | `{{ (products\|first).title }}`              | The first competition's name                    |
| `last`          | The last item in a list                             | `{{ (products\|last).title }}`               | The last competition's name                     |
| `join`          | Joins a list into one line of text                  | `{{ product.categories\|join(', ') }}`       | Cars, Featured                                  |
| `slice`         | Takes part of a list or text                        | `{% for product in products\|slice(0, 3) %}` | Loops through the first three competitions only |
| `round`         | Rounds a number                                     | `{{ 68.4\|round }}`                          | 68                                              |
| `number_format` | Formats a number with commas and decimal places     | `{{ 1234.5\|number_format(2) }}`             | 1,234.50                                        |
| `date`          | Formats a date                                      | `{{ event_date\|date('j M Y') }}`            | 5 Jan 2026                                      |
| `trim`          | Removes spaces from the start and end               | `{{ text\|trim }}`                           |                                                 |
| `escape`        | Makes text safe to show in HTML                     | `{{ text\|escape }}`                         |                                                 |

{% hint style="warning" %}
**A list cannot be printed on its own.** Writing `{{ products }}` or `{{ products|first }}` tries to print a whole list or a whole competition, which causes a **Template Error**. Always print a single field, such as `{{ product.title }}`, or loop through the list with `{% for %}`.
{% endhint %}

{% hint style="info" %}
**Text is always shown safely.** Anything you print with `{{ ... }}` is shown as plain text, so if you type HTML (such as `<b>`) into a block field or a text variable, it appears on the page as the characters themselves rather than as bold text. Put your HTML in the template, and keep the variables for the words.
{% endhint %}

***

### Styling Your Templates <a href="#styling-your-templates" id="styling-your-templates"></a>

Add a `<style>` block at the top of your template. You can use Twig inside it, which is a great way to match your site's colours automatically:

```twig
<style>
  .my-section {
    background: {{ settings.primary_color }};
    color: {{ settings.button_text_color }};
    padding: 40px;
  }
</style>

<section class="my-section">
  <h1>{{ title }}</h1>
</section>
```

{% hint style="info" %}
**Use your own CSS and icons.** Write all the styling your section needs in its `<style>` block rather than relying on class names from elsewhere on your site, as those can change. Icon fonts (such as Font Awesome) are not loaded on your site, so for icons paste in inline SVG code, which you can copy from free icon sites, or use an emoji.
{% endhint %}

{% hint style="warning" %}
**Give your CSS classes unique names.** Your styles apply to the whole page, so a class called `.title` or `.card` could accidentally restyle other parts of your site. Use a prefix that is unique to the section, such as `.hero-title` or `.promo-card`.
{% endhint %}

***

### Links to Your Competitions <a href="#links-to-your-competitions" id="links-to-your-competitions"></a>

Competition links (such as `product.url` and `winner.product_url`) and image addresses (such as `product.image_url`) are always full web addresses, so you can use them as they are:

```twig
<a href="{{ product.url }}">Enter Now</a>
```

This produces a link like `https://yoursite.co.uk/competition/win-a-bmw-m3`.

***

### Learn More <a href="#learn-more" id="learn-more"></a>

* [**Custom Twig Block**](/advanced/twig-templating/custom-twig-block.md): every variable type, every competition and winner field, live countdowns, progress bars, quick add buttons and complete examples.
* [**Custom Twig Product Grid**](/advanced/twig-templating/custom-twig-product-grid.md): design your own competition cards.
* [**Custom Twig Slider**](/advanced/twig-templating/custom-twig-slider.md): build your own hero or slider section.
* [**Settings Variables**](/advanced/twig-templating/settings-variables.md): your site colours, logos, name, social links and review scores.
* [**Header and Footer Variables**](/advanced/twig-templating/header-and-footer-variables.md): what custom headers and footers can show.
* [**Club Variables**](/advanced/twig-templating/club-variables.md): your Club tiers, benefits and the visitor's membership.

### Need Help? <a href="#need-help" id="need-help"></a>

Copy the relevant page (including the **AI Context** section at the bottom) and share it with an AI assistant, such as ChatGPT or Claude, along with a description or screenshot of what you want. It can write the template for you and help you fix any **Template Error** messages. If you get stuck, contact RaffleX support.

***

### AI Context <a href="#ai-context" id="ai-context"></a>

**For AI Assistants:** This is RaffleX's Twig templating overview. Users write custom HTML + Twig layouts in the page builder. Templates run in a sandbox with HTML autoescaping on.

**Where Twig is used:**

* Custom Twig Block: user defined variables (see [Custom Twig Block](/advanced/twig-templating/custom-twig-block.md)).
* "Custom Twig (Advanced)" layout on these blocks, with these variables:
  * Sliders: `title`, `value`, `subtitle`, `subvalue`, `featured_image_url`, `products` loop (see [Custom Twig Slider](/advanced/twig-templating/custom-twig-slider.md))
  * Product grid: one `product` per card, plus a separate CSS editor (see [Custom Twig Product Grid](/advanced/twig-templating/custom-twig-product-grid.md))
  * Big picture content: `title`, `description`, `button_text`, `button_url`, `image_url`
  * Call to action one: `title`, `description`, `button_text`, `button_url`
  * Gallery: `title`, `description`, `gallery` (array of `url`, `name`)
  * Social links: `title`, `facebook`, `instagram`, `twitter`, `youtube`, `tiktok`
  * Winners display: `title`, `description`, `gallery` (array of `url`, `name`)
  * Instant Winners Counter: `winners_today` (integer)
* Custom Club page (Club, then Advanced): `club`, `tiers`, `main_competition`, `daily_draw`, `member`, `user` (see [Club Variables](/advanced/twig-templating/club-variables.md)).
* Every template also receives `settings` (see [Settings Variables](/advanced/twig-templating/settings-variables.md)).

**Available Twig Tags:** `if` (with `elseif`, `else`), `for` (with `else`, and the `loop` variable), `set`

**Available Filters:** `upper`, `lower`, `date`, `number_format`, `default`, `length`, `first`, `last`, `join`, `slice`, `round`, `trim`, `escape`

**Not available:** Twig functions, other tags (such as `include`, `macro`, `block`), the `raw` filter, and any filter not listed above. Using them causes a template error.

**Key notes:**

1. Output is HTML autoescaped. HTML stored in variables prints as text. Never print a whole array (for example `{{ products }}` or `{{ products|first }}`); print a field or loop instead, otherwise rendering fails.
2. Competition and winner URLs are absolute (for example `https://yoursite.co.uk/competition/slug`).
3. Put CSS in a `<style>` block at the top of the template, with unique class names. Twig variables can be used inside it.
4. No icon font (such as FontAwesome) is loaded on the site. Use inline SVG or emoji for icons, and write all CSS in the template rather than relying on site utility classes.
5. Alpine.js components `raffleCountdown`, `raffleProgress` and `raffleQuickAdd` are available in every template (see [Custom Twig Block](/advanced/twig-templating/custom-twig-block.md#dynamic-components)).
