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)
Figure 1: Storefront API fetch function that reads the token from a meta tag, then fetches collection products via GraphQL.
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:
Fetch products from Shopify using Storefront API (GraphQL)
Cache results so multiple carousels don't spam requests
Create reusable product cards from normalized product objects
Append cards efficiently to the DOM
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.
Figure 3: Product card builder (part 2) outputs the final markup with lazy-load-ready images and optional badges.
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)
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:
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.
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)
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)
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
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
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
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.