How to Build Swtek’s Dynamic Product Carousels (Without Apps)
Editor's Pick

stylus_note Swtek Editorial
schedule 9 Min Read
How to Build Swtek’s Dynamic Product Carousels (Without Apps)

A lightweight, data-driven Shopify carousel built with the Storefront API, vanilla JavaScript, and performance in mind.

Swtek product carousels – a modular pipeline: fetch → cache → render cards → lazy-load images → initialize sections.

Introduction

Modern eCommerce storefronts live or die by speed, clarity, and reuse. For swtek.io, I wanted product carousels that felt like a first-class part of the brand — not a heavy injected app, and not a one-off theme hack.

This article breaks down how Swtek's dynamic product carousels work, from data fetching, to product card generation, to lazy loading and section initialization, using a clean modular JavaScript pipeline powered by Shopify's Storefront API (GraphQL).

"The goal isn't a fancy slider library — it's a fast, reusable carousel system that stays under our control."

We'll walk through six core pieces and how they connect into a reliable "Swtek-trademark" carousel system.

The Carousel Pipeline (How It All Fits Together)

fetchCollectionData reading token from meta tag and building GraphQL query
Figure 1: Storefront API fetch function that reads the token from a meta tag, then fetches collection products via GraphQL.
createCard function with escaping and product normalization
Figure 2: Product card builder (part 1) normalizes product data and safely escapes content before rendering HTML.

At a high level, each carousel section is generated by a small pipeline:

  1. Fetch products from Shopify using Storefront API (GraphQL)
  2. Cache results so multiple carousels don't spam requests
  3. Create reusable product cards from normalized product objects
  4. Append cards efficiently to the DOM
  5. Observe images and lazy-load them as they approach the viewport

The key design rule is simple: each function does one job. When each piece stays focused, the whole system becomes easier to reuse and easier to maintain.

createCard function markup output including lazy load attributes and badges
Figure 3: Product card builder (part 2) outputs the final markup with lazy-load-ready images and optional badges.
IntersectionObserver lazy loading implementation with rootMargin and unobserve
Figure 4: IntersectionObserver implementation that promotes data-src into src only when images are near the viewport.

This modular layout gives Swtek a carousel system that is fast by default, and flexible enough to power multiple sections (featured, bestsellers, bargains, new arrivals) with minimal duplication.

Data Fetching with Storefront API (GraphQL)

Storefront API fetch function using meta token and GraphQL query
Figure 1: GraphQL data fetch that reads the Storefront token from a theme-injected meta tag (keeps tokens out of code screenshots).

Instead of depending on Liquid loops, Swtek's carousels fetch product data directly using Shopify's Storefront API. GraphQL is a great fit here because it allows you to request only the data your UI needs — no more, no less.

There's also a practical performance choice in the fetch: mobile fetches fewer products than desktop. By adjusting the first count (22 on mobile, 40 on desktop), the system reduces payload size and DOM work where it matters most.

For article-safe publishing, the Storefront API token is injected using a theme setting and output as:

<meta name="storefront-token" content="{{ settings.storefront_token }}">

Your JavaScript reads that meta tag at runtime, which keeps the token out of repo screenshots while you work toward a server-side proxy solution later.

  • Why GraphQL? Efficient field selection and predictable payloads.
  • Why device-aware limits? Better performance, especially for mobile users.
  • Why a meta token? Quick implementation that avoids hardcoding sensitive values in screenshots.

Building Product Cards (Reusable UI)

Once product nodes are returned from the API, the carousel needs a reliable way to turn them into UI. That's the job of createCard.

  1. Normalize product data into predictable values
  2. Compute card-specific logic (badges, pricing, vendor labels)
  3. Render final HTML in a reusable layout
  4. Prepare images for lazy loading using data-src

Keeping card-building logic in one place prevents UI drift across sections and makes design updates much easier. If the card layout changes, you update one function — not four different carousel implementations.

Card Builder – Data Normalization & Safety (Part 1)

createCard function part 1 showing escaping, variant extraction and badges
Figure 2: The first half of createCard normalizes product fields and escapes dynamic values before inserting HTML.

Focus: safe HTML rendering + predictable product data

This part of the function does the "boring but important" work. It pulls in the fields the UI needs and makes sure the output remains stable even when product data changes or contains unexpected characters.

Notable details include:

  • Escaping values that will be inserted into attributes or markup
  • Extracting first-variant pricing and handling missing data safely
  • Calculating a "New" badge based on createdAt
  • Deriving service labels from tags (business rules stay centralized)

Card Builder – Markup Output & Lazy-Load Preparation (Part 2)

createCard function part 2 showing innerHTML with data-src images and special badge
Figure 3: The final card markup outputs lazy-load-ready images via data-src and includes optional decorative badges.

Focus: reusable markup + performance-friendly images

This portion returns the final markup for each product card. The key performance trick is that carousel images are not immediately loaded. Instead, the card uses:

  • data-src for lazy-load control
  • srcset and sizes for responsive image selection
  • loading="lazy" and decoding="async" as additional hints

Even Swtek's decorative "WINTEK'S CHOICE" ribbon is lazy-loaded. Because it's visual-only, it's also marked with alt="" and aria-hidden="true" to avoid noisy repeated announcements for assistive tech.

Performance – Lazy Loading with IntersectionObserver

IntersectionObserver lazy loading code and lazyLoadImages function
Figure 4: A single IntersectionObserver instance loads images early using rootMargin, then unobserves each image after it's loaded.

Result: faster initial paint + reduced bandwidth on mobile

Carousels can become performance traps if they render many products at once. The IntersectionObserver approach avoids that by loading only what the user is about to see.

Swtek's observer strategy:

  • Preload slightly before visibility with rootMargin: "300px 0px"
  • Use a low threshold so loading begins quickly
  • After an image loads, remove data-src and unobserve it
  • Observe images within the specific container for each carousel (no global scanning)

It's lightweight, avoids scroll event listeners, and scales well even as more carousels are added.

Caching – Reducing Duplicate Requests

fetchCollectionDataCached function using sessionStorage for caching
Figure 5: A minimal sessionStorage cache prevents multiple carousels from refetching the same collection during a session.

Why it matters: fewer API calls + snappier repeated renders

When a page contains multiple product sections, caching quickly becomes worth it. Even a simple session-based cache can eliminate duplicate network work and improve perceived speed.

This caching layer is intentionally minimal. It stores the fetched JSON keyed by collection handle (and a version suffix), then returns cached data immediately when available.

Later, this same pattern can be upgraded to a server-side proxy (Cloudflare Worker) for even stronger token handling and shared caching across users.

System Summary (What Makes It "Swtek")

Piece Role Why It's Useful Performance Impact
Storefront API Fetch Loads products via GraphQL Fetch only the fields the UI needs Lower payload size
Session Cache Reuses collection results Avoid duplicate API requests Faster repeat loads
createCard Builds product card markup Reusable UI across sections Stable DOM output
IntersectionObserver Loads images when needed Stops offscreen image loading Major mobile win
loadProductSection Orchestrates carousels One function, many sections Efficient DOM insert

The "Swtek" part isn't any single function — it's the pipeline. Each piece stays small and purposeful, and the system scales without turning into a spaghetti theme file.

Performance: Lazy Loading with IntersectionObserver

Performance is the reason this system exists. Loading dozens of images and heavy markup upfront makes carousels feel sluggish and increases bounce risk — especially on mobile.

With the observer approach, initial page render stays lighter, and users only pay the cost of image loading when they scroll toward the section. Combined with mobile-aware product limits and caching, the overall experience feels faster and more intentional.

This is also one of the best "quiet wins" for perceived quality: the site feels responsive even when showing a lot of products.

Orchestration: Loading Sections with One Function

The final piece is the orchestration function that makes the whole carousel system reusable: loadProductSection.

Instead of duplicating logic for "Featured", "Bestsellers", "Bargains", and "Arrivals", this function takes a small set of parameters and handles everything:

  • Validate section type and find the correct collection handle
  • Fetch (or cache-hit) collection products
  • Shuffle product order for freshness
  • Build cards using createCard
  • Append efficiently using a DocumentFragment
  • Start observing images inside the container
loadProductSection orchestrator function building fragment and calling lazyLoadImages
Figure 6: loadProductSection orchestrates the carousel pipeline: fetch → build cards → append fragment → start lazy loading.

This is the backbone that makes the carousels feel like a "Swtek-trademark" feature: modular, fast, and easy to scale across the storefront.

Want to Build Storefront Features Like This?

Swtek is built with a performance-first mindset — clean UI components, fast delivery, and a storefront engineered to stay responsive even as the catalog grows.

shopping_cart Browse Collections

External Links & Resources

link
..Interested in more?

Subscribe to our Newsletter

Product updates, early access, and tech insights — occasionally.

arrow_back Zurück zum Blog
forum

Hinterlasse einen Kommentar

Comments are moderated before appearing publicly to ensure a helpful and respectful discussion space. Thanks for your patience!

Bitte beachte, dass Kommentare vor der Veröffentlichung freigegeben werden müssen.