Add a Form to Product Page in Shopify


I have received a request more than once to show a form instead of an add to cart button on a product page. You may wonder why someone would do this! Sometimes merchants have products that they do not keep in inventory locally or require purchases in bulk. Whatever the merchant reason, we can easily embed a contact form within your product page and show a simple form rather than the add to cart button. While this is on the product page, it is generally the same principle no matter where you add this form on your store. We will also distinguish when to show the form based on a product tag that matches ‘invoice’. In this tutorial we are using the Dawn theme, but it should be a straightforward copy/paste for most themes on your product liquid file.

Code on Github: https://github.com/ndrishinski/blogs/tree/master/embed-product-form

Prefer Video?

Enjoy otherwise read on!

Tag products for Contact Form

The first step is to add a tag to any product that we want this contact form to show on. To do this, navigate in the Shopify dashboard to products and click on the product you have in mind. If you are trying to apply this to an entire collection, check out how to bulk add/remove tags in my previous blog here. In the tags section, we are going to add a tag that will distinguish it from normal products. I’ve chosen ‘invoice’.

Check for invoice only products

Now in our theme editor, we are going to open up the sections/main-product.liquid file. In this file we are going to make the following additions in strategic places:

...
{%- assign product_form_id = 'product-form-' | append: section.id -%}
{% comment %} add here  {% endcomment %}
{% if product.tags contains 'invoice' %}
  {% assign show_invoice = true %}
{% else %}
  {% assign show_invoice = false %}
{% endif %}
{% comment %} add to here  {% endcomment %}
...
{%- when 'quantity_selector' -%}
{% comment %} add here  {% endcomment %}
  {% unless show_invoice %}
    ...
{% comment %} and here  {% endcomment %}
  {% endunless %}
{%- when 'popup' -%}
  ...
  {%- when 'buy_buttons' -%}  
{% comment %} add here  {% endcomment %}
  {% if show_invoice %}
    {% render 'product-invoice-form', product: product %}
  {% else %}
    {%- render 'buy-buttons', block: block, product: product, product_form_id: product_form_id, section_id: section.id, show_pickup_availability: true -%}
  {% endif %}
{% comment %} until here  {% endcomment %}
...

I’ve tried to show a line or 2 before and after where you should add the code. The code we are adding is a variable called show_invoice which we use to determine whether or not to show the product quantity input and our form. Note that we are checking for the tag that we created in the first step, it is crucial that these match exactly. We are also referencing a snippet called product-invoice-form which we will create, and we are passing the product object.

Create our form snippet

Now we want to create the snippet we just referenced. In the snippets directory, let’s create a file called product-invoice-form.liquid and paste the following CSS and liquid:

{% style %}
  /* Container styles */
  .contact-form {
    max-width: 100%;
    padding: 20px;
    background-color: #f8f8f8;
    border-radius: 5px;
  }

  /* Grid styles */
  .grid {
    display: flex;
    flex-wrap: wrap;
    margin-bottom: 20px;
  }

  .grid__item {
    flex: 1 0 50%; /* Two columns on medium screens */
    padding: 0 10px;
    box-sizing: border-box;
  }

  /* Input styles */
  input[type='text'],
  input[type='email'],
  input[type='tel'] {
    width: 100%;
    padding: 10px;
    margin-bottom: 10px;
    border: 1px solid #ccc;
    border-radius: 5px;
    box-sizing: border-box;
  }

  /* Label styles */
  label {
    display: block;
    font-weight: bold;
    margin-bottom: 5px;
  }

  /* Button styles */
  .btn {
    display: block;
    width: 100%;
    padding: 10px;
    background-color: #007bff;
    color: #fff;
    border: none;
    border-radius: 5px;
    cursor: pointer;
    transition: background-color 0.3s ease;
  }

  .btn:hover {
    background-color: #0056b3;
  }

  /* Success message styles */
  .note--success {
    color: green;
    font-weight: bold;
    margin-top: 10px;
  }
{% endstyle %}

<div class="contact-form form-vertical pcf-ui">
  {%- assign formId = 'ContactForm' -%}
  {% form 'contact', id: formId %}
    <div class="grid grid--half-gutters">
      <p>Because of large demand, we require an invoice request for this product.</p>
      <div class="grid__item medium-up--one-half">
        <label for="{{ formId }}-name">Name <span aria-hidden="true">*</span></label>
        <input
          type="text"
          id="{{ formId }}-name"
          name="contact[Name]"
          value="{% if form[name] %}{{ form[name] }}{% elsif customer %}{{ customer.name }}{% endif %}"
        >
      </div>
      <div class="grid__item medium-up--one-half">
        <label for="{{ formId }}-email">Email <span aria-hidden="true">*</span></label>
        <input
          type="email"
          id="{{ formId }}-email"
          name="contact[email]"
          autocorrect="off"
          autocapitalize="off"
          value="{{ form[email] }}"
          aria-required="true"
          {%- if form.errors contains 'email' -%}
            class="input--error"
            aria-invalid="true"
            aria-describedby="{{ formId }}-email-error"
          {%- endif -%}
        >
      </div>
    </div>

    <div class="grid grid--half-gutters">
      <div class="grid__item medium-up--one-half">
        <label for="{{ formId }}-phone">Phone</label>
        <input
          type="tel"
          id="{{ formId }}-phone"
          name="contact[Phone]"
          pattern="[0-9\-]*"
          value="{% if form[phone] %}{{ form[phone] }}{% elsif customer %}{{ customer.phone }}{% endif %}"
        >
      </div>
      <div class="grid__item medium-up--one-half">
        <label for="{{ formId }}-quantity">Quantity</label>
        <input
          type="tel"
          id="{{ formId }}-quantity"
          name="contact[Quantity]"
          value="{% if form[quantity] %}{{ form[quantity] }}{% else %}1{% endif %}"
        >
      </div>
    </div>

    {% if form.posted_successfully? %}
      <p class="note note--success">We have received your submission and will reach out to you soon!</p>
    {% endif %}

    {{ form.errors | default_errors }}
    <input
      style="visibility: hidden; height: 1px;"
      type="product"
      id="{{ formId }}-product"
      name="contact[Invoice Submitted]"
      value="{{ product.title }}"
    >
    <input type="submit" class="btn" value="SUBMIT INVOICE" style="margin-top: -35px">
  {% endform %}
</div>

We’ll ignore the styles and focus on the {% form %} tag. This is a Shopify form of type contact, which will send an email to the “store email” in your Shopify dashboard. We are collecting a name, email, phone and quantity. We also pass the product title in the email so we can know which product the customer is interested in. We also display a success or error message to the user.

Now if we save this and look at our specific product in the preview, we will see our form.

Conclusion

Whatever the merchant reason, we can now easily embed a contact form within your product page. While this is on the product page, it is generally the same principle no matter where you add a contact form on your store. I hope you’ve enjoyed this tutorial, let me know what you think!