Unlocking Shopify Storefront API with JavaScript: Overcoming Liquid & AJAX API Limits

In this article, we’ll explore the specific limitations of Liquid and the AJAX API, how GraphQL via the Storefront API solves them, and how to set up your access tokens securely

Unlocking Shopify Storefront API with JavaScript: Overcoming Liquid & AJAX API Limits
4 sections

When building custom features or modern user interfaces on Shopify, developers typically rely on two core tools: Liquid for server-side rendering and the Shopify AJAX Cart API for client-side interactions.

However, as store requirements grow more complex, you will inevitably hit the architectural wall of both tools. This is where the Shopify Storefront API comes in. In this article, we’ll explore the specific limitations of Liquid and the AJAX API, how GraphQL via the Storefront API solves them, and how to set up your access tokens securely.

1. Limitations of Liquid & AJAX API vs. Storefront API

1.1 Dynamic Client-Side Fetching

  • Liquid Limitation: Liquid executes strictly on the server before the HTML page is rendered. If a user interacts with your page (e.g., applying dynamic filters or switching currencies on the fly) without a full page reload, Liquid cannot help you.
  • Storefront API Solution: Built on GraphQL, the Storefront API allows client-side JavaScript to query exact fields at any point during a user's session without forcing a browser refresh.
  • 1.2 Advanced Search & Filtering

  • Liquid/AJAX API Limitation: The standard Shopify AJAX Search API offers basic search functionality with limited query customization. Filtering via Liquid is confined to single collections and bound by Liquid pagination limits.
  • Storefront API Solution: Provides robust search capabilities powered by GraphQL. You can filter products by Metafields, Variants, Price Ranges, Tags, or Vendors using cursor-based pagination for smooth, infinite-scroll experiences.
  • 1.3 Flexible Cross-Selling & Metafield Access

  • Liquid Limitation: Querying related products based on complex conditions (like matching a variant’s custom Metafield) via Liquid inflates page payload sizes or forces you to generate numerous alternate .json layout templates.
  • Storefront API Solution: Fetch deeply nested product relationships and specific Metafields in a single, lightweight GraphQL request.
  • 2. Setting Up Permissions & Securing Access Tokens

    Because the Storefront API is called directly from the client’s browser, your Storefront Access Token will be publicly visible in the frontend source code. To keep your store data safe, you must configure strict permission boundaries.

    ⚠️ The Golden Rule: Always follow the Principle of Least Privilege. Never grant permissions to read sensitive customer or order data unless your frontend specifically requires it.

    Step-by-Step Configuration in Shopify Admin:

  • Go to Shopify Admin > Settings > Apps and sales channels > Develop apps.
  • Click Create an app and give it a descriptive name (e.g., Storefront JS Client).
  • Under the Configuration tab, locate Storefront API integration and click Configure.
  • Configure Scopes (Permissions):
  • RECOMMENDED (For frontend storefronts):
  • unauthenticated_read_product_listings: Read product and collection listings.
  • unauthenticated_read_product_inventory: Read inventory levels (if displaying stock status).
  • unauthenticated_write_checkouts / unauthenticated_read_checkouts: Create and manage carts/checkouts.
  • unauthenticated_read_selling_plans: Access subscription plans.
  • DO NOT ENABLE (Unless building a dedicated customer portal):
  • unauthenticated_read_customer_tags / addresses / customers: Keep disabled to prevent unauthorized access to customer personal information.
  • Click Save and then Install App.
  • Copy the Storefront access token (This token is safe for client-side usage).
  • 3. Code Example: Fetching Products with Vanilla JavaScript

    Here is a complete, lightweight example using the native fetch API to query the 5 newest products along with their titles, prices, and featured images.

    code
    // 1. Storefront API Configuration
    const SHOPIFY_STORE_DOMAIN = 'your-shop-name.myshopify.com'; // Replace with your store domain
    const STOREFRONT_ACCESS_TOKEN = 'your_storefront_access_token_here'; // Public token with scoped permissions
    const API_VERSION = '2024-01'; // Current API version
    
    const GRAPHQL_URL = `https://${SHOPIFY_STORE_DOMAIN}/api/${API_VERSION}/graphql.json`;
    
    // 2. Define the GraphQL Query
    const PRODUCTS_QUERY = `
      query getTopProducts {
        products(first: 5, sortKey: CREATED_AT, reverse: true) {
          edges {
            node {
              id
              title
              handle
              priceRange {
                minVariantPrice {
                  amount
                  currencyCode
                }
              }
              featuredImage {
                url
                altText
              }
            }
          }
        }
      }
    `;
    
    // 3. Helper Function to Fetch Data
    async function fetchShopifyData(query, variables = {}) {
      try {
        const response = await fetch(GRAPHQL_URL, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
            'X-Shopify-Storefront-Access-Token': STOREFRONT_ACCESS_TOKEN,
          },
          body: JSON.stringify({
            query: query,
            variables: variables,
          }),
        });
    
        if (!response.ok) {
          throw new Error(`HTTP error! Status: ${response.status}`);
        }
    
        const result = await response.json();
    
        if (result.errors) {
          console.error('GraphQL Errors:', result.errors);
          return null;
        }
    
        return result.data;
      } catch (error) {
        console.error('Fetch Error:', error);
        return null;
      }
    }
    
    // 4. Execute and Process Data
    async function initStorefrontFeature() {
      const data = await fetchShopifyData(PRODUCTS_QUERY);
      
      if (data && data.products) {
        const products = data.products.edges.map(edge => edge.node);
        console.log('Retrieved Products:', products);
        
        // Example: Render items dynamically in your DOM
        /*
        products.forEach(product => {
          console.log(`Title: ${product.title} - Price: ${product.priceRange.minVariantPrice.amount} ${product.priceRange.minVariantPrice.currencyCode}`);
        });
        */
      }
    }
    
    // Run the initialization
    initStorefrontFeature();

    4. Feature Comparison & Security Takeaways

    FeatureLiquidAJAX API (Cart API)Storefront API (GraphQL)
    Execution EnvironmentServer-sideClient-sideClient-side / Headless
    Query SpeedFast on initial page loadModerateFast (fetches only requested fields)
    FlexibilityLow (tied to page reloads)Moderate (cart & basic product tasks)Very High (unrestricted public data access)
    Security RiskZero public token exposureSession-basedRequires careful Token scope configuration

    Related Articles

    10 Essential Shopify SEO Tips to Boost Your Store's Traffic
    Tips & Tricks

    10 Essential Shopify SEO Tips to Boost Your Store's Traffic

    Optimize your Shopify store for search engines with these 10 actionable SEO tips, covering setup, keywords, on-page optimization, and technical fixes. Improve your store's visibility, drive more traffic, and increase sales. Get started with Shopify SEO today!

    August 16, 20263 min
    Adding a Smooth Back-to-Top Button to Your Shopify Theme
    Tips & Tricks

    Adding a Smooth Back-to-Top Button to Your Shopify Theme

    Learn how to add a smooth back-to-top button to your Shopify theme using lightweight CSS and JS, improving navigation and enhancing user experience.

    August 13, 20263 min
    Shopify Requires Expiring Offline Access Tokens for Public Apps: What Developers Need to Know
    Tips & Tricks

    Shopify Requires Expiring Offline Access Tokens for Public Apps: What Developers Need to Know

    Shopify is making an important change to how public apps authenticate with the Admin API

    August 8, 202630 min
    Understanding Shopify Theme Check: LiquidHTML/Complexity
    Tips & Tricks

    Understanding Shopify Theme Check: LiquidHTML/Complexity

    Although this isn't a compilation or runtime error, it's an important indicator that your Liquid file has become too complex, making it harder to read, maintain, and extend over time

    July 30, 202620 min