Advanced Logic

    Complex patterns, state machines, and performance optimization

    This guide covers advanced Liquid patterns for power users who need to implement complex business logic, state management, and data transformations.

    Advanced Liquid Patterns

    Custom Helper Functions

    While Liquid doesn't support custom functions directly, you can simulate them with assign blocks and variables.

    {% comment %} Calculate tax helper {% endcomment %}
    {% liquid
      assign _price = include.price
      assign _taxRate = include.taxRate | default: 0.1
      assign _tax = _price | times: _taxRate
      assign result = _tax
    %}
    
    {% comment %} Usage {% endcomment %}
    {% liquid
      assign include = ""
      assign include.price = subtotal
      assign include.taxRate = 0.15
    %}
    Tax: ${{ result }}
    

    State Machines

    Create complex workflows with state tracking. This is useful for multi-step processes where the path depends on a combination of previous actions.

    {% liquid
      assign state = current_state | default: "initial"
      assign nextState = ""
    
      case state
        when "initial"
          if has_account == "yes"
            assign nextState = "login"
          else
            assign nextState = "registration"
          endif
    
        when "login"
          if login_successful == "yes"
            assign nextState = "dashboard"
          else
            assign nextState = "password-reset"
          endif
    
        when "registration"
          if registration_complete == "yes"
            assign nextState = "verification"
          endif
    
        when "verification"
          if verified == "yes"
            assign nextState = "dashboard"
          endif
      endcase
    %}
    
    {{ nextState }}
    

    Data Transformation Pipelines

    Chain multiple transformations to clean and format data.

    {% liquid
      assign raw = user_input
      assign cleaned = raw | strip | downcase
      assign words = cleaned | split: " "
      assign unique = words | uniq
      assign sorted = unique | sort_natural
      assign result = sorted | join: ", "
    %}
    
    Processed: {{ result }}
    

    Common Advanced Patterns

    Pattern 1: Multi-Stage Approval Workflow

    {% liquid
      assign stage = approval_stage | default: "pending"
      assign nextStage = ""
    
      if stage == "pending"
        if manager_approved == "yes"
          assign nextStage = "director-review"
        else
          assign nextStage = "rejected"
        endif
      elsif stage == "director-review"
        if director_approved == "yes"
          assign nextStage = "final-approval"
        else
          assign nextStage = "rejected"
        endif
      elsif stage == "final-approval"
        if ceo_approved == "yes"
          assign nextStage = "approved"
        else
          assign nextStage = "rejected"
        endif
      endif
    
      echo nextStage
    %}
    

    Pattern 2: Dynamic Pricing Engine

    {% liquid
      assign basePrice = base_price
      assign quantity = quantity
    
      # Volume discount
      if quantity >= 100
        assign volumeDiscount = 0.2
      elsif quantity >= 50
        assign volumeDiscount = 0.15
      elsif quantity >= 10
        assign volumeDiscount = 0.1
      else
        assign volumeDiscount = 0
      endif
    
      # Loyalty discount
      if loyalty_years >= 5
        assign loyaltyDiscount = 0.1
      elsif loyalty_years >= 2
        assign loyaltyDiscount = 0.05
      else
        assign loyaltyDiscount = 0
      endif
    
      # Calculate
      assign subtotal = basePrice | times: quantity
      assign volumeSavings = subtotal | times: volumeDiscount
      assign afterVolume = subtotal | minus: volumeSavings
      assign loyaltySavings = afterVolume | times: loyaltyDiscount
      assign total = afterVolume | minus: loyaltySavings
    %}
    
    Subtotal: ${{ subtotal }}
    Volume Discount (-{{ volumeDiscount | times: 100 }}%): -${{ volumeSavings }}
    Loyalty Discount (-{{ loyaltyDiscount | times: 100 }}%): -${{ loyaltySavings }}
    Total: ${{ total }}
    

    Pattern 3: Risk Assessment Scoring

    {% liquid
      assign riskScore = 0
    
      # Age factor
      assign age = birth_date | diff_time: today, "year"
      if age < 25
        assign riskScore = riskScore | plus: 20
      elsif age < 35
        assign riskScore = riskScore | plus: 10
      endif
    
      # Income factor
      assign income = annual_income
      if income < 30000
        assign riskScore = riskScore | plus: 30
      elsif income < 60000
        assign riskScore = riskScore | plus: 15
      endif
    
      # Credit history
      if credit_score < 600
        assign riskScore = riskScore | plus: 40
      elsif credit_score < 700
        assign riskScore = riskScore | plus: 20
      endif
    
      # Determine level
      if riskScore >= 60
        assign riskLevel = "High"
        assign approved = false
      elsif riskScore >= 30
        assign riskLevel = "Medium"
        assign approved = true
      else
        assign riskLevel = "Low"
        assign approved = true
      endif
    %}
    
    Risk Score: {{ riskScore }}
    Risk Level: {{ riskLevel }}
    {% if approved %}Approved{% else %}Denied{% endif %}
    

    Performance Optimization

    Minimize Repeated Calculations

    Inefficient:

    Total: {{ price | times: quantity | times: 1.1 }}
    Tax: {{ price | times: quantity | times: 0.1 }}
    Subtotal: {{ price | times: quantity }}
    

    Efficient:

    {% assign subtotal = price | times: quantity %}
    Subtotal: {{ subtotal }}
    Tax: {{ subtotal | times: 0.1 }}
    Total: {{ subtotal | times: 1.1 }}
    

    Cache Complex Lookups

    {% liquid
      assign userType = membership
    
      case userType
        when "platinum"
          assign discount = 0.25
          assign priority = 1
          assign support = "24/7"
        when "gold"
          assign discount = 0.15
          assign priority = 2
          assign support = "business hours"
        else
          assign discount = 0
          assign priority = 5
          assign support = "email only"
      endcase
    %}
    

    Avoid Nested Loops

    Slow:

    {% for item in items %}
      {% for category in categories %}
        {% if item.category == category.id %}
          {{ item.name }} - {{ category.name }}
        {% endif %}
      {% endfor %}
    {% endfor %}
    

    Better:

    {% assign categoryMap = categories | map: "id" %}
    {% for item in items %}
      {{ item.name }} - {{ categoryMap[item.category] }}
    {% endfor %}
    

    Debugging Techniques

    Output Debugging

    DEBUG: {{ values | json: 2 }}
    

    Step-by-Step Tracing

    {% liquid
      echo "Step 1: Input = " | append: input
      assign cleaned = input | strip
      echo "\nStep 2: Cleaned = " | append: cleaned
      assign processed = cleaned | upcase
      echo "\nStep 3: Processed = " | append: processed
    %}
    

    Conditional Debugging

    {% if debug_mode == "yes" %}
      <pre>
      Values: {{ values | json: 2 }}
      Calculations:
      - Subtotal: {{ subtotal }}
      - Tax: {{ tax }}
      - Total: {{ total }}
      </pre>
    {% endif %}