Pin a product to top of collection page

I would like to pin a product at the top of a collection page. Much like pinning a discussion to the top of this community. No matter how a customer sorts, this item would always show as the first item in the collection.

I have tried the app “Smart Product Sorter” which claims you can pin items, but it isn’t working the way I expected.
Does anyone know of an app or workaround for this?

Thank you,

Jamie
The Winfield Collection

Maybe the easiest way around it is to make a little block with that product always up the top before the collection. You could then style the block as you like, include some extra text or similar.

I’m sure Sidekick could help you, or feel free to ask here for more help.

Nathan

Hey Jamie,

There’s a sorting setting in the collection backend called “Manually” but again if a customer sorts it from the front end then your pinned product will also get sorted out too.

Here’s a workaround:

You have two options, you can either completely remove the sorting option from the front end OR You can get it custom coded. I would recommend you to get it custom coded because that’s the recommended way for you to be able to manage your pinned product from the theme editor itself as well.

Happy to have a look at it and sort it out if you’d like.

Best,
Moeed

There is no native option to pin products.
This can be implemented by your theme or theme modification.

Some collection filtering/search apps also offer this functionality, but this is completely different thing. Or some kind of merchandising options.

Ella theme has a “product banner” – probably the best you can do without significant coding investment.

It also worth contacting theme support – they may have other suggestions.

Hi @Winfield , I tried to solve it.

Here is the video where i have pinned a product (navy jacked) and sort it again and again while the navy jacked is pinned all the time.

In this file ~/sections/main-collection-product-grid.liquid:


Here is the entire liquid file if you cannot read those images:

{{ 'template-collection.css' | asset_url | stylesheet_tag }}
{{ 'component-card.css' | asset_url | stylesheet_tag }}
{{ 'component-price.css' | asset_url | stylesheet_tag }}

{% if section.settings.image_shape == 'blob' %}
  {{ 'mask-blobs.css' | asset_url | stylesheet_tag }}
{%- endif -%}

{%- unless section.settings.quick_add == 'none' -%}
  {{ 'quick-add.css' | asset_url | stylesheet_tag }}
{%- endunless -%}

{%- if section.settings.quick_add == 'standard' -%}
  <script src="{{ 'quick-add.js' | asset_url }}" defer="defer"></script>
  <script src="{{ 'product-form.js' | asset_url }}" defer="defer"></script>
{%- endif -%}

{%- if section.settings.quick_add == 'bulk' -%}
  <script src="{{ 'quick-add-bulk.js' | asset_url }}" defer="defer"></script>
  <script src="{{ 'quantity-popover.js' | asset_url }}" defer="defer"></script>
  <script src="{{ 'price-per-item.js' | asset_url }}" defer="defer"></script>
  <script src="{{ 'quick-order-list.js' | asset_url }}" defer="defer"></script>
{%- endif -%}

{%- style -%}
  .section-{{ section.id }}-padding {
    padding-top: {{ section.settings.padding_top | times: 0.75 | round: 0 }}px;
    padding-bottom: {{ section.settings.padding_bottom | times: 0.75 | round: 0 }}px;
  }

  @media screen and (min-width: 750px) {
    .section-{{ section.id }}-padding {
      padding-top: {{ section.settings.padding_top }}px;
      padding-bottom: {{ section.settings.padding_bottom }}px;
    }
  }
{%- endstyle -%}

<div class="section-{{ section.id }}-padding gradient color-{{ section.settings.color_scheme }}">
  {%- paginate collection.products by section.settings.products_per_page -%}
    {% comment %} Sort is the first tabbable element when filter type is vertical {% endcomment %}
    {%- if section.settings.enable_sorting and section.settings.filter_type == 'vertical' -%}
      <facet-filters-form class="facets facets-vertical-sort page-width small-hide">
        <form class="facets-vertical-form" id="FacetSortForm">
          <div class="facet-filters sorting caption">
            <div class="facet-filters__field">
              <h2 class="facet-filters__label caption-large text-body">
                <label for="SortBy">{{ 'products.facets.sort_by_label' | t }}</label>
              </h2>
              <div class="select">
                {%- assign sort_by = collection.sort_by | default: collection.default_sort_by -%}
                <select
                  name="sort_by"
                  class="facet-filters__sort select__select caption-large"
                  id="SortBy"
                  aria-describedby="a11y-refresh-page-message"
                >
                  {%- for option in collection.sort_options -%}
                    <option
                      value="{{ option.value | escape }}"
                      {% if option.value == sort_by %}
                        selected="selected"
                      {% endif %}
                    >
                      {{ option.name | escape }}
                    </option>
                  {%- endfor -%}
                </select>
                <span class="svg-wrapper">
                  {{- 'icon-caret.svg' | inline_asset_content -}}
                </span>
              </div>
            </div>
          </div>

          <div class="product-count-vertical light" role="status">
            <h2 class="product-count__text text-body">
              <span id="ProductCountDesktop">
                {%- if collection.results_count -%}
                  {{
                    'templates.search.results_with_count'
                    | t: terms: collection.terms, count: collection.results_count
                  }}
                {%- elsif collection.products_count == collection.all_products_count -%}
                  {{ 'products.facets.product_count_simple' | t: count: collection.products_count }}
                {%- else -%}
                  {{
                    'products.facets.product_count'
                    | t: product_count: collection.products_count, count: collection.all_products_count
                  }}
                {%- endif -%}
              </span>
            </h2>
            {%- render 'loading-spinner' -%}
          </div>
        </form>
      </facet-filters-form>
    {%- endif -%}

    <div class="{% if section.settings.filter_type == 'vertical' %} facets-vertical page-width{% endif %}">
      {{ 'component-facets.css' | asset_url | stylesheet_tag }}
      <script src="{{ 'facets.js' | asset_url }}" defer="defer"></script>
      {%- if section.settings.enable_filtering or section.settings.enable_sorting -%}
        <aside
          aria-labelledby="verticalTitle"
          class="facets-wrapper{% unless section.settings.enable_filtering %} facets-wrapper--no-filters{% endunless %}{% if section.settings.filter_type != 'vertical' %} page-width{% endif %}"
          id="main-collection-filters"
          data-id="{{ section.id }}"
        >
          {% render 'facets',
            results: collection,
            enable_filtering: section.settings.enable_filtering,
            enable_sorting: section.settings.enable_sorting,
            filter_type: section.settings.filter_type,
            paginate: paginate
          %}
        </aside>
      {%- endif -%}

      <div
        class="product-grid-container{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--slide-in{% endif %}"
        id="ProductGridContainer"
        {% if settings.animations_reveal_on_scroll %}
          data-cascade
        {% endif %}
      >
        {%- if collection.products.size == 0 -%}
          <div class="collection collection--empty page-width" id="product-grid" data-id="{{ section.id }}">
            <div class="loading-overlay gradient"></div>
            <div class="title-wrapper center">
              <h2 class="title title--primary">
                {{ 'sections.collection_template.empty' | t -}}
                <br>
                {{
                  'sections.collection_template.use_fewer_filters_html'
                  | t: link: collection.url, class: 'underlined-link link'
                }}
              </h2>
            </div>
          </div>
        {%- else -%}
          <div
            class="collection{% if section.settings.filter_type != 'vertical' %} page-width{% endif %}"
          >
            <div class="loading-overlay gradient"></div>
            <ul
              id="product-grid"
              data-id="{{ section.id }}"
              class="
                grid product-grid grid--{{ section.settings.columns_mobile }}-col-tablet-down
                grid--{{ section.settings.columns_desktop }}-col-desktop
                {% if section.settings.quick_add == 'bulk' %} collection-quick-add-bulk{% endif %}
              "
            >
              {% assign skip_card_product_styles = false %}

              {%- comment -%}
                Pinned product: render it first, only on page 1, so it stays at the very
                top of the collection no matter how the customer sorts. Sorting only
                reorders `collection.products` below - it never touches this block.
              {%- endcomment -%}
              {%- assign pinned_product = section.settings.pinned_product -%}
              {%- if pinned_product != blank and paginate.current_page == 1 -%}
                <li
                  class="grid__item grid__item--pinned{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--slide-in{% endif %}"
                  {% if settings.animations_reveal_on_scroll %}
                    data-cascade
                    style="--animation-order: 0;"
                  {% endif %}
                >
                  {% render 'card-product',
                    card_product: pinned_product,
                    media_aspect_ratio: section.settings.image_ratio,
                    image_shape: section.settings.image_shape,
                    show_secondary_image: section.settings.show_secondary_image,
                    show_vendor: section.settings.show_vendor,
                    show_rating: section.settings.show_rating,
                    lazy_load: false,
                    skip_styles: skip_card_product_styles,
                    quick_add: section.settings.quick_add,
                    section_id: section.id
                  %}
                </li>
                {%- assign skip_card_product_styles = true -%}
              {%- endif -%}
              {%- comment -%} ------------------------------------------------  {%- endcomment -%}

              {%- for product in collection.products -%}
                {%- comment -%} ------------------------------------------------ Skip the pinned product here so it never appears twice {%- endcomment -%}
                {%- if pinned_product != blank and product.id == pinned_product.id -%}
                  {%- continue -%}
                {%- endif -%}
                {%- comment -%} ------------------------------------------------ Skip the pinned product here so it never appears twice {%- endcomment -%}
                {% assign lazy_load = false %}
                {%- if forloop.index > 2 -%}
                  {%- assign lazy_load = true -%}
                {%- endif -%}
                <li
                  class="grid__item{% if settings.animations_reveal_on_scroll %} scroll-trigger animate--slide-in{% endif %}"
                  {% if settings.animations_reveal_on_scroll %}
                    data-cascade
                    style="--animation-order: {{ forloop.index }};"
                  {% endif %}
                >
                  {% render 'card-product',
                    card_product: product,
                    media_aspect_ratio: section.settings.image_ratio,
                    image_shape: section.settings.image_shape,
                    show_secondary_image: section.settings.show_secondary_image,
                    show_vendor: section.settings.show_vendor,
                    show_rating: section.settings.show_rating,
                    lazy_load: lazy_load,
                    skip_styles: skip_card_product_styles,
                    quick_add: section.settings.quick_add,
                    section_id: section.id
                  %}
                </li>
                {%- assign skip_card_product_styles = true -%}
              {%- endfor -%}
            </ul>

            {%- if paginate.pages > 1 -%}
              {% render 'pagination', paginate: paginate, anchor: '' %}
            {%- endif -%}
          </div>
        {%- endif -%}
      </div>
    </div>
  {%- endpaginate -%}
  {% if section.settings.image_shape == 'arch' %}
    {{ 'mask-arch.svg' | inline_asset_content }}
  {%- endif -%}
</div>

{% schema %}
{
  "name": "t:sections.main-collection-product-grid.name",
  "class": "section",
  "settings": [
    {
      "type": "header",
      "content": "Pinned product"
    },
    {
      "type": "product",
      "id": "pinned_product",
      "label": "Pinned product",
      "info": "Always shows first on this collection page, no matter how customers sort. Leave empty for none."
    },
    {
      "type": "range",
      "id": "products_per_page",
      "min": 8,
      "max": 36,
      "step": 4,
      "default": 16,
      "label": "t:sections.main-collection-product-grid.settings.products_per_page.label"
    },
    {
      "type": "range",
      "id": "columns_desktop",
      "min": 1,
      "max": 6,
      "step": 1,
      "default": 4,
      "label": "t:sections.main-collection-product-grid.settings.columns_desktop.label"
    },
    {
      "type": "color_scheme",
      "id": "color_scheme",
      "label": "t:sections.all.colors.label",
      "info": "t:sections.all.colors.has_cards_info",
      "default": "scheme-1"
    },
    {
      "type": "header",
      "content": "t:sections.main-collection-product-grid.settings.header__3.content"
    },
    {
      "type": "select",
      "id": "image_ratio",
      "options": [
        {
          "value": "adapt",
          "label": "t:sections.main-collection-product-grid.settings.image_ratio.options__1.label"
        },
        {
          "value": "portrait",
          "label": "t:sections.main-collection-product-grid.settings.image_ratio.options__2.label"
        },
        {
          "value": "square",
          "label": "t:sections.main-collection-product-grid.settings.image_ratio.options__3.label"
        }
      ],
      "default": "adapt",
      "label": "t:sections.main-collection-product-grid.settings.image_ratio.label"
    },
    {
      "type": "select",
      "id": "image_shape",
      "options": [
        {
          "value": "default",
          "label": "t:sections.all.image_shape.options__1.label"
        },
        {
          "value": "arch",
          "label": "t:sections.all.image_shape.options__2.label"
        },
        {
          "value": "blob",
          "label": "t:sections.all.image_shape.options__3.label"
        },
        {
          "value": "chevronleft",
          "label": "t:sections.all.image_shape.options__4.label"
        },
        {
          "value": "chevronright",
          "label": "t:sections.all.image_shape.options__5.label"
        },
        {
          "value": "diamond",
          "label": "t:sections.all.image_shape.options__6.label"
        },
        {
          "value": "parallelogram",
          "label": "t:sections.all.image_shape.options__7.label"
        },
        {
          "value": "round",
          "label": "t:sections.all.image_shape.options__8.label"
        }
      ],
      "default": "default",
      "label": "t:sections.all.image_shape.label",
      "info": "t:sections.all.image_shape.info"
    },
    {
      "type": "checkbox",
      "id": "show_secondary_image",
      "default": false,
      "label": "t:sections.main-collection-product-grid.settings.show_secondary_image.label"
    },
    {
      "type": "checkbox",
      "id": "show_vendor",
      "default": false,
      "label": "t:sections.main-collection-product-grid.settings.show_vendor.label"
    },
    {
      "type": "checkbox",
      "id": "show_rating",
      "default": false,
      "label": "t:sections.main-collection-product-grid.settings.show_rating.label",
      "info": "t:sections.main-collection-product-grid.settings.show_rating.info"
    },
    {
      "type": "select",
      "id": "quick_add",
      "default": "none",
      "label": "t:sections.main-collection-product-grid.settings.quick_add.label",
      "info": "t:sections.main-collection-product-grid.settings.quick_add.info",
      "options": [
        {
          "value": "none",
          "label": "t:sections.main-collection-product-grid.settings.quick_add.options.option_1"
        },
        {
          "value": "standard",
          "label": "t:sections.main-collection-product-grid.settings.quick_add.options.option_2"
        },
        {
          "value": "bulk",
          "label": "t:sections.main-collection-product-grid.settings.quick_add.options.option_3"
        }
      ]
    },
    {
      "type": "header",
      "content": "t:sections.main-collection-product-grid.settings.header__1.content"
    },
    {
      "type": "checkbox",
      "id": "enable_filtering",
      "default": true,
      "label": "t:sections.main-collection-product-grid.settings.enable_filtering.label",
      "info": "t:sections.main-collection-product-grid.settings.enable_filtering.info"
    },
    {
      "type": "select",
      "id": "filter_type",
      "options": [
        {
          "value": "horizontal",
          "label": "t:sections.main-collection-product-grid.settings.filter_type.options__1.label"
        },
        {
          "value": "vertical",
          "label": "t:sections.main-collection-product-grid.settings.filter_type.options__2.label"
        },
        {
          "value": "drawer",
          "label": "t:sections.main-collection-product-grid.settings.filter_type.options__3.label"
        }
      ],
      "default": "horizontal",
      "label": "t:sections.main-collection-product-grid.settings.filter_type.label",
      "info": "t:sections.main-collection-product-grid.settings.filter_type.info"
    },
    {
      "type": "checkbox",
      "id": "enable_sorting",
      "default": true,
      "label": "t:sections.main-collection-product-grid.settings.enable_sorting.label"
    },
    {
      "type": "header",
      "content": "t:sections.main-collection-product-grid.settings.header_mobile.content"
    },
    {
      "type": "select",
      "id": "columns_mobile",
      "default": "2",
      "label": "t:sections.main-collection-product-grid.settings.columns_mobile.label",
      "options": [
        {
          "value": "1",
          "label": "t:sections.main-collection-product-grid.settings.columns_mobile.options__1.label"
        },
        {
          "value": "2",
          "label": "t:sections.main-collection-product-grid.settings.columns_mobile.options__2.label"
        }
      ]
    },
    {
      "type": "header",
      "content": "t:sections.all.padding.section_padding_heading"
    },
    {
      "type": "range",
      "id": "padding_top",
      "min": 0,
      "max": 100,
      "step": 4,
      "unit": "px",
      "label": "t:sections.all.padding.padding_top",
      "default": 36
    },
    {
      "type": "range",
      "id": "padding_bottom",
      "min": 0,
      "max": 100,
      "step": 4,
      "unit": "px",
      "label": "t:sections.all.padding.padding_bottom",
      "default": 36
    }
  ]
}
{% endschema %}

Note: Just use Shopify AI (shopify Magic) to learn about how to apply thse changes. Paste this reply into it.

You can sort the products manually in the collection to do that

Best regards,
Dan from Ryviu: Product Reviews & Loyalty app

That would produce a product grid with one hanging product at the bottom, right?

Also note that topic starter does not use Dawn.

Did he mention that he used dawn? Just modified my own theme to solve the problem.

I agree. Shopify doesn’t currently offer a native way to pin specific products to the top of a collection, so it usually comes down to your theme or a custom implementation.

If you’re looking for a quick solution, it’s definitely worth checking whether your theme includes merchandising features like featured products or product banners. Reaching out to the theme developer is also a good idea, as they may already have a built-in setting or a recommended workaround.

If you need more control—such as pinning multiple products or creating different featured products for different collections—a merchandising or collection management app may be the better long-term option, especially if you want to avoid custom code.

Thank you all for your responses. We do use Ella, not Dawn, which has code differentials. However, not a huge deal. With Ella I can create a “Featured Product” in the collection description which is not a true resolution, but will work for what we need. The item in question is not a big seller so our purchaser was hoping to feature it more to see if it sells.

Again, thank you all. I will still make attempts at the code above, but if nothing works, what we have will suffice. It would be a great feature for the future though!

Although not a block, I was able to create it in the collection description, and enable that at the top of the collection page. This is honestly the best for now and appreciate your quick reply.