How To Add Preloader in Shopify - eCommerce Thesis

How To Add Preloader in Shopify

Benefits of Using a Premium Shopify Preloader

1. Faster Perceived Loading Speed

Even if your store takes 3–5 seconds to load, the preloader makes it feel fast and smooth.
This improves user satisfaction and reduces bounce rate.

2. Increases Customer Trust

A professional, animated preloader (especially with your brand logo) instantly builds trust and shows that your store is high-quality and well-designed.

3. Better First Impression

Customers judge your store within 0.5 seconds.
A beautiful preloader gives them a premium first impression before the page loads.

4. Reduces Page Abandonment

Without a preloader, customers may think the website is broken when loading takes too long.
A loader keeps users engaged until the site is ready.

5. Strengthens Brand Identity

Using your logo or a custom animation helps reinforce your branding from the very first moment.

6. Increases Session Duration

Users who stay during load time end up spending more time on the website, which is good for conversions and SEO.

7. No SEO Risk / No CLS Issue

This preloader is built in a non-blocking, fully optimized way so your Google PageSpeed and SEO are never impacted.


Key Features of This Premium Preloader

1. Fully Dynamic from Theme Customizer

No coding needed.
Everything is editable from Online Store → Customize → Theme Settings:

  • Enable/disable preloader
  • Choose animation style
  • Upload your own logo
  • Change logo size
  • Add Lottie JSON animation

2. 5 Premium Animation Styles

You get:

✔ Pulse Logo Loader
✔ Simple Fade-in Loader
✔ 3D Rotate Loader
✔ Line Drawing Animation (looks very premium)
✔ Lottie JSON Loader (most advanced)

3. Supports SVG, PNG, JPG, and Lottie JSON

Logo-based animations work with:

  • PNG
  • SVG (best for line drawing)
  • JPG
  • Lottie JSON (ultra premium)

4. Lightweight — No Apps Needed

Completely coded with:

  • Liquid
  • CSS animations
  • Lightweight JavaScript

⚡ Loads faster than any app-based preloader.

5. ThemeForest-Level Animation Quality

Professional animations similar to:

  • Envato / ThemeForest templates
  • High-end UI/UX websites
  • Modern SaaS dashboards

6. SEO Friendly

The preloader:

  • does not block rendering
  • does not affect CLS
  • loads async
  • fades out after content is ready

7. Works on All Shopify Themes

Supports:

  • Shopify Dawn
  • Empire
  • Impulse
  • Booster
  • Motion
  • All ThemeForest-paid themes

Why This Preloader Is Important

1. Modern Websites Use It

Premium brands like:

  • Apple
  • Tesla
  • Shopify
  • Adobe

use preloaders in their websites and apps.
Now your store looks like that level.

2. Reduces User Confusion

Without a preloader, users may think:

  • “Website is broken”
  • “Internet is slow”
  • “Shopify store isn’t loading”

A loader gives clear feedback: “Please wait… store is loading.”

3. Improves UX on Slow Devices / Networks

Many mobile users in Asia, Africa, Middle East use slow networks.
Preloader improves experience for all.

4. Helps With Conversion Rate Optimization (CRO)

Smooth loading experience =
higher trust =
more users stay =
more purchases.

5. Brand Presentation Starts Instantly

Even before the homepage loads, your brand appears through the logo animation.


Quick overview (what you’ll do)

  1. Add Preloader settings to config/settings_schema.json (theme customizer controls).
  2. Create a new section sections/preloader.liquid and paste the full preloader code.
  3. Include that section in layout/theme.liquid before </body>.
  4. Upload Lottie JSON file (if using Lottie) and paste its URL into theme settings.
  5. Test, tweak size/style, and check performance & accessibility.

1) Add Theme Settings (Customizer controls)

File: config/settings_schema.json
Open and insert this block before the final ] (or merge into your existing preloader group if present):

{
  "name": "Preloader Settings",
  "settings": [
    {
      "type": "checkbox",
      "id": "enable_preloader",
      "label": "Enable Preloader",
      "default": true
    },
    {
      "type": "image_picker",
      "id": "preloader_logo",
      "label": "Preloader Logo (SVG recommended)"
    },
    {
      "type": "select",
      "id": "preloader_style",
      "label": "Preloader Style",
      "options": [
        { "label": "Logo Pulse (Default)", "value": "pulse" },
        { "label": "Gradient Wave Loader", "value": "gradient" },
        { "label": "SVG Line Drawing Loader", "value": "line" },
        { "label": "3D Rotate Logo", "value": "rotate3d" },
        { "label": "Lottie JSON Animation", "value": "lottie" },
        { "label": "Fade-In Reveal Logo", "value": "fade" },
        { "label": "Minimal Circle Loader", "value": "minimal" },
        { "label": "Glassmorphism Floating Logo", "value": "glass" },
        { "label": "Neon Glow Logo", "value": "neon" },
        { "label": "Liquid Gooey Loader", "value": "gooey" },
        { "label": "Gooey Logo Reveal", "value": "gooey-reveal" },
        { "label": "Brand Color Ripple", "value": "ripple" },
        { "label": "Morphing Shape Loader", "value": "morph" },
        { "label": "Orbiting Dots", "value": "orbit" },
        { "label": "Floating Bubbles", "value": "bubbles" },
        { "label": "Sliding Logo Reveal", "value": "slide" },
        { "label": "Pixelation Logo Loader", "value": "pixel" }
      ],
      "default": "pulse"
    },
    {
      "type": "number",
      "id": "preloader_logo_size",
      "min": 40,
      "max": 200,
      "step": 5,
      "label": "Logo Size (px)",
      "default": 100
    },
    {
      "type": "url",
      "id": "lottie_url",
      "label": "Lottie JSON URL (Optional for Lottie Loader)",
      "info": "Upload JSON to Shopify Files and paste the direct link here"
    }
  ]
}

Save the file. Now Theme Editor will show Preloader Settings.


2) Create the Section: sections/preloader.liquid

File: sections/preloader.liquid
Create a new section (name exactly preloader.liquid) and paste the entire code below. This is the single-file, all-17 styles preloader.

Important: This file contains CSS, SVG filters, HTML selection logic and JS to hide the preloader after window.load. It is self-contained.

{% comment %}
PREMIUM UNIVERSAL PRELOADER SECTION
All 17 animation styles included
Dynamically controlled from Theme Settings
Author: ChatGPT – Premium Shopify Animation Pack
{% endcomment %}

{% if settings.enable_preloader %}
<style>
#site-preloader {
  position: fixed; inset:0;
  background:#fff;
  display:flex; justify-content:center; align-items:center;
  z-index:999999;
  transition:opacity .4s ease, visibility .4s ease;
}
#site-preloader.hidden { opacity:0; visibility:hidden; }

/* -------- 1. Pulse -------- */
.pulse { animation:pulseAnim 1.2s infinite ease-in-out; width: auto; height: auto;}
@keyframes pulseAnim { 0%,100%{transform:scale(1);opacity:.8;} 50%{transform:scale(1.15);opacity:1;} }

/* -------- 2. Gradient Wave -------- */
.gradient-wave { width:180px;height:180px;background:radial-gradient(circle,#eee,#ccc);border-radius:50%;position:relative;animation:waveSpin 1.5s infinite linear; }
.gradient-wave img { width:70%; position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); }
@keyframes waveSpin {100%{transform:rotate(360deg);}}

/* -------- 3. SVG Line Draw -------- */
.line-draw-logo { display:block; }

/* -------- 4. 3D Rotate -------- */
.logo-3d { animation:rot3d 1.5s linear infinite; }
@keyframes rot3d { 0%{transform:rotateY(0deg);}100%{transform:rotateY(360deg);} }

/* -------- 5. Fade-In -------- */
.fade-logo { animation:fadeLoop 1.4s infinite; }
@keyframes fadeLoop { 0%{opacity:0;}50%{opacity:1;}100%{opacity:0;} }

/* -------- 6. Minimal Circle -------- */
.minimal-loader { width:40px;height:40px;border:4px solid #ddd;border-top-color:#000;border-radius:50%;animation:minSpin 1s linear infinite; }
@keyframes minSpin { 100%{transform:rotate(360deg);} }

/* -------- 7. Glassmorphism -------- */
.glass-loader { width:200px;height:200px;backdrop-filter:blur(12px);background:rgba(255,255,255,.25);border:1px solid rgba(255,255,255,.4);border-radius:24px;display:flex;justify-content:center;align-items:center;animation:floatAnim 2s infinite ease-in-out; }
.glass-logo { width:60%; }
@keyframes floatAnim { 0%,100%{transform:translateY(0);}50%{transform:translateY(-12px);} }

/* -------- 8. Neon Glow -------- */
.neon-logo { width:150px; filter:drop-shadow(0 0 12px #0ff); animation:neonPulse 1.5s infinite; }
@keyframes neonPulse { 0%,100%{filter:drop-shadow(0 0 6px #0ff);}50%{filter:drop-shadow(0 0 22px #0ff);} }

/* -------- 9. Gooey Bubbles -------- */
.gooey-container { width:120px;height:40px; display:flex;justify-content:space-between; filter:url(#gooeyFilter); }
.gooey-container span { width:20px;height:20px;background:#000;border-radius:50%; animation:gooMove .8s infinite alternate; }
@keyframes gooMove { to{transform:translateY(-10px);} }

/* -------- 10. Gooey Logo Reveal -------- */
.gooey-reveal img { width:160px; animation:gooReveal 2s infinite; }
@keyframes gooReveal { 0%{clip-path:circle(0% at 50% 50%);}60%{clip-path:circle(80% at 50% 50%);}100%{clip-path:circle(0% at 50% 50%);} }

/* -------- 11. Ripple Loader -------- */
.ripple-loader { position: relative; width: 220px; height: 220px; display:flex; align-items:center; justify-content:center; }
.ripple-loader div { position:absolute; border:3px solid #000; border-radius:50%; animation:rippleAnim 1.6s infinite; opacity: .9; }
.ripple-loader div:nth-child(1){width:80px;height:80px;}
.ripple-loader div:nth-child(2){width:110px;height:110px;animation-delay:.4s;}
.ripple-loader div:nth-child(3){width:140px;height:140px;animation-delay:.8s;}
@keyframes rippleAnim { 0%{opacity:1;transform:scale(.3);} 100%{opacity:0;transform:scale(1);} }

/* -------- 12. Morph Shape -------- */
.morph-shape { width:200px;height:200px;background:#eee;border-radius:30% 70% 60% 40%/40% 60% 70% 30%; animation:morphing 3s infinite; }
@keyframes morphing { 0%,100%{border-radius:30% 70% 60% 40%/40% 60% 70% 30%;} 50%{border-radius:60% 40% 30% 70%/70% 30% 40% 60%;} }

/* -------- 13. Orbit Dots -------- */
.orbit-wrapper { width:160px;height:160px;position:relative; display:flex; align-items:center; justify-content:center; }
.orbit-dot { width:14px;height:14px;background:#000;border-radius:50%; position:absolute; animation:orbitDot 1.4s infinite linear; }
.orbit-logo { width:80px; position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); }
@keyframes orbitDot { 100%{transform:rotate(360deg) translateX(60px) rotate(-360deg);} }

/* -------- 14. Bubbles -------- */
.bubble-loader { position:relative; width:160px; height:160px; display:flex; align-items:center; justify-content:center; }
.bubble-loader span { width:20px;height:20px;background:#000;border-radius:50%;position:absolute; animation:bubbleUp 1.2s infinite ease-in-out; }
@keyframes bubbleUp { from{transform:translateY(20px);opacity:.4;} to{transform:translateY(-30px);opacity:1;} }

/* -------- 15. Slide Reveal -------- */
.slide-logo { width:150px; transform:translateX(-100%); animation:slideAnim 1.6s infinite; }
@keyframes slideAnim { 0%{transform:translateX(-100%);}50%{transform:translateX(0);}100%{transform:translateX(100%);} }

/* -------- 16. Pixel Loader -------- */
#pixelCanvas { width:150px; image-rendering:pixelated; animation:pixelBlur 1.3s infinite; }
@keyframes pixelBlur { 0%{filter:blur(5px);}50%{filter:blur(0);}100%{filter:blur(5px);} }

/* small responsive tweaks */
#site-preloader img { max-width: 100%; height: auto; display:block; }
</style>

<!-- Gooey Filter -->
<svg style="position:absolute;width:0;height:0">
  <filter id="gooeyFilter">
    <feGaussianBlur in="SourceGraphic" stdDeviation="10" result="blur"/>
    <feColorMatrix in="blur" mode="matrix"
      values="1 0 0 0 0  0 1 0 0 0  0 0 1 0 0  0 0 0 20 -10"/>
  </filter>
</svg>

<div id="site-preloader" aria-hidden="true" role="status" aria-label="Loading">
  {% case settings.preloader_style %}
    {% when 'pulse' %}
      <img class="pulse" src="{{ settings.preloader_logo | img_url: '600x' }}" style="width:{{ settings.preloader_logo_size }}px;" alt="Loading">

    {% when 'gradient' %}
      <div class="gradient-wave"><img src="{{ settings.preloader_logo | img_url: '600x' }}" style="width:{{ settings.preloader_logo_size }}px;" alt="Loading"></div>

    {% when 'line' %}
      <svg class="line-draw-logo" width="{{ settings.preloader_logo_size }}" height="{{ settings.preloader_logo_size }}" viewBox="0 0 200 200" aria-hidden="true">
        <image href="{{ settings.preloader_logo | img_url: '600x' }}" width="200" height="200" />
      </svg>

    {% when 'rotate3d' %}
      <img class="logo-3d" src="{{ settings.preloader_logo | img_url: '600x' }}" style="width:{{ settings.preloader_logo_size }}px;" alt="Loading">

    {% when 'fade' %}
      <img class="fade-logo" src="{{ settings.preloader_logo | img_url: '600x' }}" style="width:{{ settings.preloader_logo_size }}px;" alt="Loading">

    {% when 'minimal' %}
      <div class="minimal-loader" role="status" aria-label="Loading"></div>

    {% when 'glass' %}
      <div class="glass-loader"><img class="glass-logo" src="{{ settings.preloader_logo | img_url: '600x' }}" alt="Loading"></div>

    {% when 'neon' %}
      <img class="neon-logo" src="{{ settings.preloader_logo | img_url: '600x' }}" style="width:{{ settings.preloader_logo_size }}px;" alt="Loading">

    {% when 'gooey' %}
      <div class="gooey-container" aria-hidden="true"><span></span><span></span><span></span></div>

    {% when 'gooey-reveal' %}
      <div class="gooey-reveal"><img src="{{ settings.preloader_logo | img_url: '600x' }}" style="width:{{ settings.preloader_logo_size }}px;" alt="Loading"></div>

    {% when 'ripple' %}
      <div class="ripple-loader" aria-hidden="true">
        <div></div><div></div><div></div>
        <img src="{{ settings.preloader_logo | img_url: '600x' }}" class="ripple-logo" style="width:{{ settings.preloader_logo_size }}px; position:relative; z-index:2;" alt="Loading">
      </div>

    {% when 'morph' %}
      <div class="morph-shape" aria-hidden="true"></div>

    {% when 'orbit' %}
      <div class="orbit-wrapper" aria-hidden="true">
        <div class="orbit-dot"></div>
        <img class="orbit-logo" src="{{ settings.preloader_logo | img_url: '600x' }}" style="width:{{ settings.preloader_logo_size }}px;" alt="Loading">
      </div>

    {% when 'bubbles' %}
      <div class="bubble-loader" aria-hidden="true"><span></span><span></span><span></span><span></span></div>
      <img class="bubble-logo" src="{{ settings.preloader_logo | img_url: '600x' }}" style="width:{{ settings.preloader_logo_size }}px; opacity:0.0; position:absolute;" alt="">

    {% when 'slide' %}
      <img class="slide-logo" src="{{ settings.preloader_logo | img_url: '600x' }}" style="width:{{ settings.preloader_logo_size }}px;" alt="Loading">

    {% when 'pixel' %}
      <canvas id="pixelCanvas" width="200" height="200" aria-hidden="true"></canvas>
      <img id="pixelSource" src="{{ settings.preloader_logo | img_url: '600x' }}" style="display:none" alt="">

    {% when 'lottie' %}
      {% if settings.lottie_url != blank %}
        <div id="lottie-animation" style="width:{{ settings.preloader_logo_size }}px; height:auto;" aria-hidden="true"></div>
      {% else %}
        <!-- fallback to pulse if no Lottie URL -->
        <img class="pulse" src="{{ settings.preloader_logo | img_url: '600x' }}" style="width:{{ settings.preloader_logo_size }}px;" alt="Loading">
      {% endif %}
  {% endcase %}
</div>

<!-- Pixel canvas JS: converts image into pixel effect (optional, small script below) -->
<script>
(function(){
  // Lottie loader script injection (only when selected)
  {% if settings.preloader_style == 'lottie' and settings.lottie_url != blank %}
    var s = document.createElement('script');
    s.src = "https://cdnjs.cloudflare.com/ajax/libs/bodymovin/5.7.6/lottie.min.js";
    s.onload = function(){
      try {
        lottie.loadAnimation({
          container: document.getElementById('lottie-animation'),
          renderer: 'svg',
          loop: true,
          autoplay: true,
          path: "{{ settings.lottie_url }}"
        });
      } catch(e) { console.warn('Lottie load error', e); }
    };
    document.head.appendChild(s);
  {% endif %}

  // Pixel canvas rendering (for 'pixel' style)
  {% if settings.preloader_style == 'pixel' %}
    window.addEventListener('load', function(){
      try {
        var img = document.getElementById('pixelSource');
        var canvas = document.getElementById('pixelCanvas');
        var ctx = canvas.getContext('2d');
        // draw lower-res version for pixelated effect
        img.onload = function(){
          var w = canvas.width, h = canvas.height;
          ctx.imageSmoothingEnabled = false;
          ctx.clearRect(0,0,w,h);
          ctx.drawImage(img,0,0,w,h);
        };
        if (img.complete) img.onload();
      } catch(e) { console.warn('Pixel effect error', e); }
    });
  {% endif %}

  // Hide preloader once page fully loads
  window.addEventListener('load', function(){
    var pre = document.getElementById('site-preloader');
    if(!pre) return;
    setTimeout(function(){ pre.classList.add('hidden'); pre.setAttribute('aria-hidden','true'); }, 200);
  });
})();
</script>

{% endif %}

Save the section.


3) Include the Section in theme layout

File: layout/theme.liquid (or layout/main.liquid depending on theme)
Find </body> and paste just before it:

{% section 'preloader' %}

Save the layout. The section will now be included on all pages.


4) Upload Lottie JSON (if using Lottie)

If you plan to use the Lottie option:

  1. Go to Shopify Admin → Content → Files.
  2. Click Upload files → choose your .json Lottie file.
  3. After upload, click the file and copy the URL shown. It looks like:
    https://cdn.shopify.com/s/files/1/XXXX/XXXX/files/animation.json?v=123456
  4. Go to Online Store → Customize → Theme Settings → Preloader Settings and paste that URL into Lottie JSON URL.
  5. Set Preloader Style → Lottie and Logo Size as needed.

5) Theme Editor: Configure & Test

Go to Online Store → Customize → Theme Settings → Preloader Settings:

  • Toggle Enable Preloader on/off.
  • Upload your preloader logo (SVG recommended for crispness & line draw).
  • Choose Preloader Style (pulse/gradient/line/… pixel).
  • Enter Lottie JSON URL if you selected Lottie.
  • Set Logo Size (px).

Preview (use device simulator and network throttling) to check appearance.


6) Accessibility & SEO considerations

  • The preloader is non-blocking and hidden after window.load — it should not block rendering or cause CLS (content layout shift).
  • We add aria-hidden="true" and role="status" to the preloader to avoid screen reader confusion. You can adjust labeling if you want audible feedback.
  • Keep the preloader short and simple — long, complex Lottie files increase resource size. Prefer compressed Lottie JSON.
  • Use SVG logo for best sharpness and small file size.

7) Performance tips

  • Use settings.preloader_logo | img_url: '600x' or smaller depending on intended display size. The section uses 600x as a safe default — you can change to '300x' to reduce bytes.
  • Keep Lottie JSON under 200 KB if possible. Use Lottie optimizers on lottiefiles.com.
  • Defer any heavy scripts; the section only loads the lottie lib when lottie style is selected.
  • Avoid extremely long animations — they run while the site loads and may annoy users.

8) Troubleshooting checklist

  • Preloader not showing?
    • Confirm settings.enable_preloader is true in Theme Editor.
    • Confirm sections/preloader.liquid is included in layout/theme.liquid.
  • Lottie not playing?
    • Ensure settings.lottie_url is a direct link to the .json in Shopify Files (starts with https://cdn.shopify.com/.../files/...json).
    • Make sure the lottie script loaded; check browser console for errors.
  • Logo looks pixelated?
    • Upload a higher-res SVG/PNG and increase preloader_logo_size or change img_url size.
  • Preloader won’t hide?
    • Check for JS errors in console; any script errors can stop the load listener.
    • Confirm the window.load event fires (if heavy deferred resources, it may delay). You can temporarily change .addEventListener('load',...) to a timeout for testing.

9) Optional extras (copy/paste snippets)

9.1 Disable preloader on mobile (example)

If you want to disable preloader for mobile devices to reduce perceived delay, wrap inclusion with a small check—replace the include in theme.liquid:

{% assign ua = request.user_agent | downcase %}
{% unless ua contains 'mobile' and ua contains 'iphone' %}
  {% section 'preloader' %}
{% endunless %}

(Or implement JS inside section to detect screen width and immediately hide for small widths.)

9.2 Force fallback if no logo uploaded

Inside sections/preloader.liquid, you can replace image usage with:

{% assign logo_url = settings.preloader_logo | default: 'https://cdn.shopify.com/s/files/.../default-logo.png' %}
<img src="{{ logo_url | img_url: '600x' }}">

10) Final testing checklist (before publishing)

  • Preview on Desktop, Mobile (Chrome devtools device modes).
  • Test with Slow 3G network in DevTools to see perceived load.
  • Test Lottie URL in an incognito window.
  • Check Lighthouse/Pagespeed: preloader should not cause CLS or block critical rendering.
  • Check console for JS errors.
  • Accessibility check: toggling screen reader should not read preloader content repeatedly.