Published on

Mastering Metaobjects in Shopify A Step-by-Step Guide to Solving Discount Function Dilemmas

Authors
  • avatar
    Name
    Entaice Braintrust
    Twitter

Mastering Metaobjects in Shopify: A Step-by-Step Guide to Solving Discount Function Dilemmas

I remember the first time I sat down with a cup of coffee — the kind that made me feel like I could write code with my eyes closed — and dove headfirst into a Shopify project. My laptop screen lit up with endless lines of JavaScript, and the glow of opportunity filled the room. In that whirlwind of caffeine-induced ambition, one problem stuck out like a mischievous glitch in the matrix: integrating dynamic metaobject logic in a Shopify discount function using the run.js file. Sound familiar? Let’s unravel this mystery together and find a way to call those elusive metaobjects.

The Mysterious World of Metaobjects

Alright, buckle up, code wranglers. We're diving into the core of the problem. Picture this: you need to fetch some metaobjects from Shopify's Storefront API dynamically. You're ready to weave some magic into your discount function, but how does one simply call metaobjects in the ever-mysterious run.js file? Just like Frodo needed a Fellowship, we need guidance. Here’s how we embark on this journey:

Step 1: Preparing Your Toolkit

Just as every quest starts with the right gear, let's ensure we’ve got the essentials. You'll be working with the Shopify Storefront API – exciting, right? Make sure you have your store's GraphQL endpoint and access token at hand. These are akin to your map and compass. Here's a sneak peek into your toolkit:

const API_URL = '/api/2023-10/graphql' // Your store's endpoint
const ACCESS_TOKEN = '' // Your personal golden ticket

Step 2: Crafting the Perfect Query

Like crafting the perfect potion, we need the right mix of ingredients to fetch our metaobjects. This involves scripting a GraphQL query. No need to summon a wizard; we’ve got this:

const query = `
  query FetchMetaobjects($type: String!) {
    metaobjects(first: 10, type: $type) {
      edges {
        node {
          id
          type
          fields {
            key
            value
          }
        }
      }
    }
  }
`

Step 3: Let the Fetching Begin

Armed with your query, it’s time to send it off into the vast digital landscape. Implementing the fetchMetaobjects function is akin to sending a raven. Remember the raven must reach its destination:

async function fetchMetaobjects(type) {
  const response = await fetch(API_URL, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Shopify-Storefront-Access-Token': ACCESS_TOKEN,
    },
    body: JSON.stringify({ query, variables: { type } }),
  })

  const result = await response.json()
  if (!response.ok) {
    console.error('Failed to fetch metaobjects:', result.errors)
    return []
  }

  return result.data.metaobjects.edges.map((edge) => edge.node)
}

Step 4: Integrating Metaobjects into Your Discount Function

With our metaobjects fetched and ready to go, let’s integrate them into our discount function like a well-composed symphony. Compare dates, check cart items, apply discounts – all in perfect harmony:

Here’s the heart of the process, the main orchestrator:

export async function run(input) {
  const metaobjects = await fetchMetaobjects('free-gift')
  const today = new Date()
  const FREE_GIFT_VARIANT_ID = 'gid://shopify/ProductVariant/43187542556808'
  const cart = input.cart

  const eligibleCampaign = METAOBJECTS.find((campaign) => {
    const startDate = new Date(campaign.dateStart)
    const endDate = new Date(campaign.dateEnd)

    if (today < startDate || today > endDate) {
      return false
    }

    const nonGiftProducts = cart.lines.filter(
      (line) => line.merchandise.id !== FREE_GIFT_VARIANT_ID
    )

    const matchesPriceRange =
      cart.cost.totalAmount.amount >= campaign.rules.cartPriceRange.min &&
      cart.cost.totalAmount.amount <= campaign.rules.cartPriceRange.max

    return nonGiftProducts.length > 0 && matchesPriceRange
  })

  if (!eligibleCampaign) {
    return EMPTY_DISCOUNT
  }

  const existingFreeGift = cart.lines.find((line) => line.merchandise.id === FREE_GIFT_VARIANT_ID)

  if (existingFreeGift && existingFreeGift.quantity > 1) {
    return EMPTY_DISCOUNT
  }

  return {
    discounts: [
      {
        targets: [
          {
            productVariant: {
              id: FREE_GIFT_VARIANT_ID,
            },
          },
        ],
        value: {
          percentage: {
            value: '100.0',
          },
        },
      },
    ],
    discountApplicationStrategy: DiscountApplicationStrategy.First,
  }
}

As we wrap up this coding saga, remember, the beauty of coding is in its journey. Each line and function a step closer to perfection. It's not just about solving a problem, but about crafting a story, much like a good book or a melodious song. Let's sip our coffee, admire our handiwork, and prepare for the next challenge that lies ahead. We've got this, coding fellowship!