Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.fourthwall.com/llms.txt

Use this file to discover all available pages before exploring further.

Every Custom Code section consists of three parts: styles, markup, and script. Together, these give you full control over appearance, content, and behavior.

Basic structure

<!-- 1. STYLES — Section-specific CSS -->
<style>
  .my-section-{{ section.id }} {
    max-width: 1200px;
    margin: 0 auto;
    padding: 48px 16px;
  }
</style>

<!-- 2. MARKUP — HTML with Liquid logic -->
<section class="my-section-{{ section.id }}">
  <h2>My Custom Section</h2>

  {%- assign collection = collections['all'] -%}

  {% for product in collection.products limit: 4 %}
    <div>
      <h3>{{ product.title }}</h3>
      <p>{{ product.price | money }}</p>
    </div>
  {% endfor %}
</section>

<!-- 3. SCRIPT — JavaScript scoped to the section -->
<script>
  (function() {
    const section = document.querySelector('.my-section-{{ section.id }}');
    if (!section) return;

    // Your JavaScript logic here
  })();
</script>

Styles

Place your CSS inside a <style> tag at the top of the section. Always scope styles to section.id to prevent conflicts when multiple instances of the same section exist on a page.
<style>
  .my-section-{{ section.id }} {
    padding-top: 36px;
    padding-bottom: 36px;
  }

  @media screen and (min-width: 640px) {
    .my-section-{{ section.id }} {
      padding-top: 48px;
      padding-bottom: 48px;
    }
  }
</style>
Always use section.id in your CSS selectors. Without it, styles from one section instance will leak into others.

Markup

The markup section contains HTML mixed with Liquid tags and objects. This is where you define the visual structure and dynamic content of your section.
<section class="my-section-{{ section.id }}">
  <div class="container">
    <h2>Featured Products</h2>

    {%- assign collection = collections['all'] -%}

    {% for product in collection.products limit: 8 %}
      <div class="product-card">
        <img src="{{ product.featured_image | img_url: 'large' }}" alt="{{ product.title }}">
        <h3>{{ product.title }}</h3>
        <p>{{ product.price | money }}</p>
        <a href="{{ product.url | localized_url }}">View product</a>
      </div>
    {% endfor %}
  </div>
</section>

Key objects in markup

ObjectDescription
sectionThe current section instance
section.idUnique identifier for this section instance
collectionsAll product collections (accessed by handle)
membership_tiersAll membership tiers

Script

Place your JavaScript inside a <script> tag. Scope DOM queries to the section root so multiple instances of the same section don’t interfere with each other, and wrap your code in an IIFE to avoid leaking variables into the global scope.
<script>
  (function() {
    const section = document.querySelector('.my-section-{{ section.id }}');
    if (!section) return;

    const button = section.querySelector('.toggle');
    const panel = section.querySelector('.panel');

    button.addEventListener('click', function() {
      panel.classList.toggle('is-open');
    });
  })();
</script>
Always scope DOM queries to the section instance. Using document.querySelector('.toggle') without a section root will match elements across every instance of the section on the page.

Best practices

Scope CSS with section.id

Always include section.id in class names to prevent style conflicts:
<style>
  .my-section-{{ section.id }} .title {
    font-size: 24px;
  }
</style>
<section class="my-section-{{ section.id }}">
  <h2 class="title">Featured Products</h2>
</section>

Use responsive design

Apply mobile-first styles with media queries:
<style>
  .my-section-{{ section.id }} {
    padding-top: 36px;
  }

  @media screen and (min-width: 640px) {
    .my-section-{{ section.id }} {
      padding-top: 48px;
    }
  }
</style>

Check for blank values

Always check if values exist before rendering:
{% if product.featured_image %}
  <img src="{{ product.featured_image | img_url: 'large' }}" alt="{{ product.title }}">
{% endif %}

{% if product.compare_at_price %}
  <s>{{ product.compare_at_price | money }}</s>
{% endif %}

Limit product iterations

Always use the limit filter when iterating over product collections to control performance:
{%- assign collection = collections['all'] -%}

{% for product in collection.products limit: 8 %}
  <div class="product">{{ product.title }}</div>
{% endfor %}