Section reuse on pages other than Home

Highlighted
Shopify Partner
2 0 3

As far as I know you can only use sections on pages other than the "Home" page by including:

{% section "my-section" %}

 

Now you might have a section "image" and want to use it twice on your "About us" page. It looks like it's not possible because the sections cannot have unique contents.

...
{% section "image" %}
...
{% section "image" %}
...

 

I have already thought that it sucks that you cannot use sections on pages other than Home but if you cannot even reuse them when including them, they are basically useless on all pages other than Home, aren't they? Is there a possiblity to get this working?

So sad. :(

Highlighted
Shopify Partner
4 0 0

Check out Advanced ThemeBuilder in the App Store. it allows the placement of sections into any page, product, post, or collection.

Out of the box it allows sections to go at the top and/or bottom of any content, and advanced uses can create custom zones to place sections mid-content, like after the main product description.

We've been using this App in beta in over a dozen stores over the past year. It has been incredibly helpful.

0 Likes
Highlighted
Shopify Partner
6 0 9

Hey there, we came up with a workaround and wrote a guide which requires no additional plugins or fees and it is fairly easy to implement. Here is the how-to: https://oak.works/blog/technical/2017/03/23/shopify-sections-editor/

 

Highlighted
Shopify Partner
2 0 0

Steve, I know I'm jumping in much later, I just want to say that this is absolutely brilliant, and was a really helpful write-up. Thanks so much.

0 Likes
Highlighted
Shopify Partner
34 1 13

If someone is still interested, we provided different approach to this problem here:

https://community.shopify.com/c/Shopify-Design/How-can-i-add-sections-to-a-regular-page/m-p/516155/h...

:)

Best,

Lucas

Open Source Shopify App Store - https://github.com/sellfino/sellfino
Free apps ready to download on GitHub

Join our awesome community! Here is how you can connect with us:
Website - all info here + live chat
Discord - channels to discuss new ideas and ask for help
Messanger - if you want to chat on Facebook
Email - whenever we are out of touch, drop us a message
0 Likes
Highlighted
Shopify Partner
2 0 0

We are going to try this now. If it works this is a genius! Thanks for posting.

0 Likes
Highlighted
Tourist
5 0 4

For anyone still looking for a different solution, here's what worked for us. It's NOT a dynamic solution (ie: you won't be able to use the customizer to edit the section on your page – it's all hardcoded). However, it's a great solution for a homepage section you'd like to re-use and won't need updating via the customizer.

 

1. View page source for your homepage

2. Find the HTML for the section you're looking to re-use (it will begin with a div looking something like this: div id="shopify-section-1570644431335")

3. Highlight and copy the entire div and its contents 

4. Go into your Themes section and click Edit Code under your active theme

5. Add a new Snippet in the Snippets folder, and title it whatever you'd like

6. Paste the HTML into your new snippet and click save

7. Next, create a new page template and title it whatever you'd like

8. Look for something like this on your new page template:

    <div class="content-container narrow rte">
      <h1>{{ page.title }}</h1>
      {{ page.content }}
    </div>

9. Use the following code to insert your new snippet wherever you'd like in relation to the page.title or page.content objects:

{% include 'whatever-you-named-your-snippet' %}

10. Save your new page template

11. Open the page you're wanting to include the custom section on in the Pages menu

12. Under template on the right hand side of your screen, use the drop-down to select your new page template and click save.

 

You might need to stylize with additional spacing or CSS in the page template, but this is a sure-fire way to reuse any homepage section anywhere on your site. Hope this helps someone!

0 Likes
Highlighted
Shopify Partner
18 2 2

@Steve_Ross Really helpful and great write up. Please write more articles on your blog!

 

Do you have some example snippets to get this to work? I am trying it out right now and for example I need to create a snippet_hero-banner, what does that look like on your end. I cannot seem to get the image to load on the screen.

 

Thanks!

 

0 Likes
Highlighted
New Member
2 1 2

@Steve_Ross gives a great solution. However it is missing some details about how to create the snippets, as @aquasar  is pointing out. I have been using Shopify for a couple of days and was facing the same problem, for which I found a solution very similar to Steve's one before stumbling upon this post.

To answer your question in more details:

In my case, I basically wanted to improve the custom-content.liquid section and use that as a way to create multiple home-like pages. 

Your theme default sections are usually pretty complete and it would be silly not to take advantage of that. No need to create new snippets from scratch!

To start with, create a new section, and let's name it advanced-custom-content.liquid, and let's fill it in with a skeleton:

 

<div>
  {% for block in section.blocks %}
    <div class="grid-item" {{ block.shopify_attributes }}>
      {% case block.type %}

      // This is where you identify what type of block you are using and include the correct snippet.

      {% endcase %}
    </div>
  {% endfor %}
</div>

{% schema %}
{
  "name": "Advanced custom content",
  "class": "index-section",
  "settings": [
    {
      "type": "text",
      "id": "title",
      "label": "Heading",
      "default": "Custom content"
    }
  ],
  "blocks": [], // This is where you will add the schema for all the snippets types you created.
  "presets": [
    {
      "name": "Custom content",
      "category": "Advanced layout"
    }
  ]
}
{% endschema %}

 

 

Now, we need to fill in the skeleton with the actual sections we want to be able to reuse in the editor. For example, I want to be able to reuse the hero.liquid section, so I need to convert it to a snippet. Here is how you can do it:

 

A section is in general made of 2 main pieces:

  • Some content ➞ This is what you will convert to a snippet
  • A schema ➞ You will need to append the content of this to the "blocks" array in my the schema of advanced-custom-content.liquid.

Let's start with the schema, then we will take care of converting the code of the section to reuse into a snippet.

 

1. Adding the schema 

Take the schema of hero.liquid, and do the following:

  • Remove the "preset" field.
  • Save the content of the  "class" field (we will use it later), and remove that field.
  • Add a new field: "type" which will be used in the body of your customizable section to know what type of block you are dealing with. In my case, I named it 'hero'.

The new schema should look like this:

 

{
  "name": "Image with text overlay",
  "type": "hero", // this will be the tag to identify this type of block
  "settings": [
    {
      "type": "image_picker",
      "id": "image",
      "label": "Image"
    },
    {
      "type": "select",
      "id": "alignment",
      "label": "Image alignment",
      "default": "center",
      "options": [
        {
          "value": "top",
          "label": "Top"
        },
        {
          "value": "center",
          "label": "Middle"
        },
        {
          "value": "bottom",
          "label": "Bottom"
        }
      ]
    },
    {
      "type": "select",
      "id": "hero_layout",
      "label": "Layout",
      "default": "full_width",
      "options": [
        {
          "label": "Full width",
          "value": "full_width"
        },
        {
          "label": "Fixed width",
          "value": "fixed_width"
        }
      ]
    },
    {
      "type": "select",
      "id": "hero_size",
      "label": "Section height",
      "default": "medium",
      "options": [
        {
          "label": "Adapt to image",
          "value": "adapt"
        },
        {
          "label": "Extra Small",
          "value": "x-small"
        },
        {
          "label": "Small",
          "value": "small"
        },
        {
          "label": "Medium",
          "value": "medium"
        },
        {
          "label": "Large",
          "value": "large"
        },
        {
          "label": "Extra Large",
          "value": "x-large"
        }
      ]
    },
    {
      "type": "text",
      "id": "title",
      "label": "Heading",
      "default": "Image with text overlay"
    },
  {
      "type": "select",
      "id": "header_size",
      "label": "Header size",
      "default": "medium",
      "options": [
        {
          "label": "Medium",
          "value": "medium"
        },
        {
          "label": "Large",
          "value": "large"
        }
      ]
    },
    {
      "type": "richtext",
      "id": "text",
      "label": "Text",
      "default": "<p>Use overlay text to give your customers insight into your brand. Select imagery and text that relates to your style and story.</p>"
    },
{
      "type": "select",
      "id": "text_size",
      "label": "Text size",
      "default": "medium",
      "options": [
        {
          "label": "Medium",
          "value": "medium"
        },
        {
          "label": "Large",
          "value": "large"
        },
        {
          "label": "Extra Large",
          "value": "x-large"
        }
      ]
    },
    {
      "type": "text",
      "id": "button_label",
      "label": "Button label"
    },
    {
      "type": "url",
      "id": "button_link",
      "label": "Button link"
    },
    {
      "type": "checkbox",
      "id": "show_overlay",
      "label": "Show overlay",
      "default": true
    }
  ]
}

 

 

Once you have done that, just append this schema to the "blocks" array in your advanced-custom-content.liquid file's schema.

Note: And I keep in mind that the "class" of the original schema was: "index-section index-section--flush"

Note 2: I wish there was a way to put this piece of schema into a snippet and invoke it in advanced-custom-content.liquid's schema, but unfortunately Shopify's framework will not allow to do that.

 

2. Convert hero.liquid to a snippet

Create a new file in the Snippets directory: hero-snippet.liquid.

Copy the content of the original hero.liquid section file except for the {% schema %}, and do the following:

  • Replace any occurrence of "section.settings" with "block.settings". This is because now the settings of the section that you converted into a snippet are in the "blocks" array of the advanced-custom-content.liquid file. 

Important note: make sure to replace  "section.settings" with "block.settings" and not just any occurrence of "section" with "block", because there are other occurrences of "section" that have nothing to do with the settings and you don't want to screw that up.

  • Insert that modified content inside your hero-snippet.liquid file, surrounded by the following html: <div class="[put here the content of the "class" field you previously saved from hero.liquid]">...</div>

 

Your new hero-snippet.liquid file should look like this:

 

<div class="index-section index-section--flush">
  {%- if block.settings.hero_layout == 'full_width' and block.settings.hero_size == 'adapt' -%}
    {%- if block.settings.image.aspect_ratio == blank -%}
      {%- assign min_aspect_ratio = 2.0 -%}
    {%- else -%}
      {%- assign min_aspect_ratio = block.settings.image.aspect_ratio -%}
    {%- endif -%}
    {%- assign wrapper_height = 100 | divided_by: min_aspect_ratio -%}
    {%- style -%}
      .hero-{{ section.id }} {
        height: {{- wrapper_height -}}vw !important;
      }
    {%- endstyle -%}
  {%- endif -%}
  <div data-section-id="{{ section.id }}" data-section-type="hero-section">
    {%- if block.settings.hero_layout == 'fixed_width' -%}
      <div class="page-width">
    {%- endif -%}
    {%- if block.settings.hero_layout == 'fixed_width' and block.settings.hero_size ==  'adapt' -%}
      {%- assign slide_width = 1090 -%}
      {%- assign min_aspect_ratio = block.settings.image.aspect_ratio | default: 2.0 -%}
      <div class="hero-fixed-width hero--adapt"
           id="Hero-{{ section.id }}"
           data-layout="{{ block.settings.hero_layout }}">
        {%- assign img_url = block.settings.image | img_url: '1x1' | replace: '_1x1.', '_{width}x.' -%}
        {%- if block.settings.image.width < max_width -%}
          {%- assign slide_width = block.settings.image.width -%}
        {%- endif -%}
        <div class="hero-fixed-width__content">
          <div class="page-width text-center">
            {%- if block.settings.title != blank -%}
              <h2 class="h1 mega-title{% if block.settings.text_size == 'large' %} mega-title--large{% endif %}">{{ block.settings.title | escape }}</h2>
            {%- endif -%}
            {%- if block.settings.text != blank -%}
              <div class="rte-setting mega-subtitle{% if block.settings.text_size == 'large' %} mega-subtitle--large{% endif %}">{{ block.settings.text }}</div>
            {%- endif -%}
            {%- if block.settings.button_label != blank and block.settings.button_link != blank -%}
              <a href="{{ block.settings.button_link }}" class="btn hero__btn">
                {{ block.settings.button_label | escape }}
              </a>
            {%- endif -%}
          </div>
        </div>
        {%- if block.settings.image != blank -%}
          <img class="hero-fixed-width__image lazyload lazypreload"
               src="{{ block.settings.image | img_url: '300x300' }}"
               data-src="{{ img_url }}"
               data-widths="[180, 360, 470, 600, 770, 970, 1060, 1280, 1512, 1728, 2048]"
               data-aspectratio="{{ block.settings.image.aspect_ratio }}"
               data-sizes="auto"
               style="{%- if slide_width <= max_width -%}
                        {%- assign min_width = slide_width | times: 100 | divided_by: max_width -%}
                        min-width: {{ min_width }}%;
                      {%- endif -%}
                      object-position: {{ block.settings.alignment }};"
               alt="{{ block.settings.image.alt | escape }}">
        {%- else -%}
          <span>
            {% capture current %}{% cycle 1, 2 %}{% endcapture %}
            {{ 'lifestyle-' | append: current | placeholder_svg_tag: 'placeholder-svg' }}
          </span>
        {%- endif -%}
        <noscript>
          <div class="hero-fixed-width__image"{% if block.settings.image %}{% unless block.settings.image.alt == blank %} role="img" aria-label="{{ block.settings.image.alt | escape }}"{% endunless %} style="background-image: url('{{ block.settings.image | img_url: '2048x' }}'); background-position: center {{ block.settings.alignment }};"{% endif %}></div>
        </noscript>
      </div>
    {%- else -%}
      <div class="hero hero--{{ block.settings.hero_size }} hero-{{ section.id }}{% if block.settings.show_overlay %}{% if block.settings.title != blank or block.settings.text != blank or block.settings.button_label != blank %} hero__overlay{% endif %}{% endif %} box ratio-container lazyload js"
           id="Hero-{{ section.id }}"
           data-layout="{{ block.settings.hero_layout }}"
           {%- if block.settings.image -%}
            {% unless block.settings.image.alt == blank %}
            role="img"
            aria-label="{{ block.settings.image.alt | escape }}"
            data-alt="{{ block.settings.image.alt | escape }}"
            {% endunless %}
           data-bg="{{ block.settings.image | img_url: '300x300' }}"
           data-bgset="{% include 'bgset', image: block.settings.image %}"
           data-sizes="auto"
           data-parent-fit="cover"
           style="background-position: {{ block.settings.alignment }}; background-image: url('{{ block.settings.image | img_url: '300x300' }});"
           {%- endif -%}>
      {%- if block.settings.image == blank -%}
        <div class="placeholder-background">
          {{ 'lifestyle-1' | placeholder_svg_tag: 'placeholder-svg' }}
        </div>
      {%- endif -%}
        <div class="hero__inner">
          <div class="page-width text-center">
            {%- if block.settings.title != blank -%}
              {%- if block.settings.header_size == 'medium' -%}
                  <h2 class="h1 mega-title">{{ block.settings.title | escape }}</h2>
              {%- elsif block.settings.header_size == 'large' -%}
                  <h2 class="h1 mega-title mega-title--large">{{ block.settings.title | escape }}</h2>
              {%- endif -%}
            {%- endif -%}
            {%- if block.settings.text != blank -%}
              {%- if block.settings.text_size == 'medium' -%}
                  <div class="rte-setting mega-subtitle">{{ block.settings.text }}</div>
              {%- elsif block.settings.text_size == 'large' -%}
                  <div class="rte-setting mega-subtitle mega-subtitle--large">{{ block.settings.text }}</div>
              {%- elsif block.settings.text_size == 'x-large' -%}
                  <div class="rte-setting mega-subtitle mega-subtitle--x-large">{{ block.settings.text }}</div>
              {%- endif -%}
            {%- endif -%}
            {%- if block.settings.button_label != blank and block.settings.button_link != blank -%}
              {%- capture ariaLabel -%}
                {{- block.settings.button_label -}}
                {%- if block.settings.button_link.type == 'frontpage_link' -%}
                  : {{ 'homepage.general.title' | t -}}
                {%- elsif block.settings.button_link.type == 'catalog_link' -%}
                  : {{ 'collections.catalog.title' | t -}}
                {%- elsif block.settings.button_link.object.title -%}
                  : {{ block.settings.button_link.object.title -}}
                {%- endif -%}
              {%- endcapture -%}
  
              <a href="{{ block.settings.button_link }}"
                class="btn hero__btn"
                aria-label="{{ ariaLabel }}">
                {{- block.settings.button_label | escape -}}
              </a>
            {%- endif -%}
          </div>
        </div>
      </div>
      <noscript>
        <div class="hero hero--{{ block.settings.hero_size }}{% if block.settings.show_overlay %}{% if block.settings.title != blank or block.settings.text != blank or block.settings.button_label != blank %} hero__overlay{% endif %}{% endif %}"{% if block.settings.image %}{% unless block.settings.image.alt == blank %} role="img" aria-label="{{ block.settings.image.alt | escape }}"{% endunless %} style="background-image: url('{{ block.settings.image | img_url: '2048x' }}'); background-position: center {{ block.settings.alignment }};"{% endif %}></div>
      </noscript>
    {%- endif -%}
    {%- if block.settings.hero_layout == 'fixed_width' -%}
      </div>
    {%- endif -%}
  </div>
</div>

 

 

3. Invoke hero-snippet in advanced-custom-content.liquid

Now that you have your snippet, let's invoke it in advanced-custom-content.liquid by simply updating the {% case %} statement:

 

<div>
  {% for block in section.blocks %}
    {% case block.type %}

      {%- when 'hero' -%}
        {% include 'hero-snippet' %}

    {% endcase %}
  {% endfor %}
</div>

 

 

Et voilà... You just created an advanced-custom-content.liquid section with a hero subsection. Repeat the process for every section you want to add to your new advanced-custom-content template. In the picture below, you can see that I added the "Image with text overlay" (hero), "Image with text" and "Video" sections, as well as a "Custom HTML" that I am currently working on:

Advanced Custom Cntent section with a few sub sectionsAdvanced Custom Cntent section with a few sub sections

 

If you want to use this in your editor, you can create a new file page.advanced-custom-content.liquid in the Templates directory, and simply put that one line in it:

 

 

{% section 'advanced-custom-content' %}

 

You'll be able to create a new page based on that template to modify within the Shopify editor. 


Cheers!

0 Likes