Product pages - Get customization information for products

Topic summary

Core Topic:
Implementing line item properties on Shopify product pages to collect customer customization information (e.g., engraving text, personalization details, file uploads).

Key Implementation Steps:

  • Create alternate product templates (product.customizable.liquid) with custom form fields
  • Add HTML input elements with name="properties[Field Name]" syntax
  • Use Shopify UI Elements Generator tool for generating form field code
  • Ensure inputs are placed inside product <form> tags or use HTML5 form attribute

Common Technical Challenges:

  • Theme compatibility: Tutorial designed for older sectioned/non-sectioned themes; newer themes (Dawn, OS 2.0) use .json templates requiring different approaches
  • Missing quantity selectors: Custom fields sometimes hide quantity pickers; fix by enabling “Show quantity selector” in theme settings
  • “Submit” button location: Varies by theme; often found in snippets (product-info.liquid, product-form.liquid) rather than main template
  • Quick view/Buy Now buttons: May bypass required customization fields; requires separate implementation

Data Visibility & Export:

  • Line item properties stored as strings appear at checkout; integers/underscore-prefixed values hidden from customers but visible in admin
  • Properties visible in Admin > Orders but not automatically included in standard CSV exports
  • Third-party apps (EZ Exporter, Mechanic) recommended for bulk data extraction

Current Status:
Thread remains active with ongoing troubleshooting for OS 2.0 themes. Many users successfully implement basic text fields but struggle with advanced features (conditional logic, file uploads, styling consistency). Official Shopify support explicitly not provided for this customization.

Summarized with AI on November 1. AI used: claude-sonnet-4-5-20250929.

Thank you so much for the complete answer Paul, being extremely new to coding I only understood half of what you said.

Do you think you can tell me, if my line codes are outside the “form”

Thank you again :slight_smile:

{%- assign current_variant = product.selected_or_first_available_variant -%}
{%- assign current_variant_sale = false -%}
{% if current_variant.compare_at_price > current_variant.price %}
{%- assign current_variant_sale = true -%}
{% endif %}
{% assign featured_media = current_variant.featured_media | default: product.featured_media %}

{% comment %}

Product Featured Media

{% endcomment %}

{% assign variant_media_ids = '' %}

{%- unless product.has_only_default_variant -%}

{% for variant in product.variants %}
{% assign variant_media = variant.featured_media %}

{%- if variant_media -%}

{%- if variant_media_ids contains variant_media.id -%}
{% continue %}
{%- endif -%}

{% assign variant_media_ids = variant_media_ids | append: variant_media.id | append: ’ ’ %}
{% assign featured = false %}
{%- if featured_media == variant_media -%}
{% assign featured = true %}
{%- endif -%}

{% include ‘product-preview-image’ with media: variant_media, featured_media: featured, gallery_type: ‘media’, data_image: ‘data-variant-media-image’ %}
{%- endif -%}

{% endfor %}
{%- endunless -%}

{% unless featured_media and variant_media_ids contains featured_media.id %}
{% include ‘product-preview-image’ with media: featured_media, featured_media: true, gallery_type: ‘media’, data_image: ‘data-variant-media-image’ %}
{%- endunless -%}

{% include ‘shopify-xr-button’ %}

{% comment %}

Product Form & Description

{% endcomment %}

{% if section.settings.show_vendor %}
{{ product.vendor }}
{% endif %}

{{ product.title }}

{{ ‘products.product.sale_price’ | t }}
{{ ‘products.product.price’ | t }}
{{ current_variant.price | money }}

{{ ‘products.product.regular_price’ | t }}
{{ current_variant.compare_at_price | money }}

{% include ‘product-unit-price’, variant: current_variant %}

{%- if shop.taxes_included or shop.shipping_policy.body != blank -%}

{%- if shop.taxes_included -%} {{ 'products.product.include_taxes' | t }} {%- endif -%} {%- if shop.shipping_policy.body != blank -%} {{ 'products.product.shipping_policy_html' | t: link: shop.shipping_policy.url }} {%- endif -%}
{%- endif -%}
{{ product.description }}
Votre prénom

{% include ‘product-form’ %}
{% if section.settings.show_share_buttons %}
{% if settings.share_facebook or settings.share_twitter or settings.share_pinterest %}

{% include 'social-sharing', type: "product", links: 'bottom' share_title: product.title, share_permalink: product.url, share_image: featured_media %}
{% endif %} {% endif %}

{% comment %}

Product Share Buttons

{% endcomment %}
{% if section.settings.show_share_buttons %}
{% if settings.share_facebook or settings.share_twitter or settings.share_pinterest %}

{% include 'social-sharing', type: 'mobile', share_title: product.title, share_permalink: product.url, share_image: featured_media %}
{% endif %} {% endif %}

{% comment %}

Product Media Gallery

{% endcomment %}
{%- if product.media.size > 1 -%}

{% comment %}
If we are hiding variant media which are displayed at the top of the
page, then find total number media not set as a variant media or as the
featured media.

We need the total number of media to be displayed so that we know what
arrangement the media need to be positioned in, i.e. rows of 3 or 2
media.
{% endcomment %}

{%- if section.settings.hide_variant_media -%}
{% assign variant_media_ids_array = variant_media_ids | split: ’ ’ %}
{% assign total_media = product.media.size | minus: variant_media_ids_array.size %}
{%- else -%}
{% assign total_media = product.media.size %}
{%- endif -%}

{% comment %}
Insert images into rows of 3 and/or 2 depending on the total number of
images.
{% endcomment %}
{% assign total_modulus = total_media | modulo: 3 %}

{% if total_media == 1 %}

{% endif %}

{% for media in product.media %}

{% unless variant_media_ids contains media.id and section.settings.hide_variant_media %}
{% capture data_image %}
data-parent-fit=“cover”
{% endcapture %}

{% include ‘product-preview-image’ with media, featured_media: false, gallery_type: ‘submedia’, data_image: data_image %}

{% endunless %}
{% endfor %}

{% if total_media == 1 %}

{% endif %}
{% endif %}

{% comment %}

Product Slideshow

{% endcomment %}
{% unless product.media.size == 0 %}

{% include 'icon-close' %}
{% for media in product.media %} {%- capture product_media_wrapper_class -%} product-slideshow__slide slider__slide{%- if forloop.first %} slider__slide--active {%- endif -%} {%- endcapture -%}

{% include ‘media’ with media,
section_type: ‘slideshow’,
parent_fit: ‘contain’,
featured_media: true,
data_image: ‘data-product-slideshow-image’,
product_media_wrapper_class: product_media_wrapper_class,
product_media_wrapper_data: ‘data-product-slideshow-slide’,
image_class: ‘fade-in’
%}
{% endfor %}

{% include ‘shopify-xr-button’ %}

{% unless product.media.size == 1 %}

{% include ‘icon-arrow-left’ %}
{{ ‘general.pagination.previous’ | t }}

{% include ‘icon-arrow-right’ %}
{{ ‘general.pagination.next’ | t }}

{% for media in product.media %} {{ 'sections.product_template.slide' | t: number: forloop.index }} {% endfor %}
{% endunless %}
{% endunless %}

{% comment %}

Product Data

{% endcomment %}