Example functions

Copy-paste starting points you can drop into a new function and adapt. Every function has the same shape - export default async function (input, ctx) - where input is the JSON from Flow (or the Variables tab) and ctx gives you ctx.log, ctx.fetch, and (when enabled) ctx.shopify.graphql. New here? Start with How to create a function and Passing variables into your function.

Small: the basics

No permissions or setup needed - paste one in and press Test.

Make an HTTP requestjavascript
export default async function (input, ctx) {
  const response = await ctx.fetch('https://jsonplaceholder.typicode.com/todos/1');

  if (!response.ok) {
    throw new Error(`Request failed with status ${response.status}`);
  }

  const json = await response.json();
  ctx.log('Fetched todo:', json);

  return json;
}
Read the input from Flowjavascript
export default async function (input, ctx) {
  // Everything Flow (or the Variables tab) sends arrives as `input`.
  ctx.log('Received input:', input);

  return {
    received: input,
    itemCount: Array.isArray(input.items) ? input.items.length : 0,
  };
}

Medium: variables, secrets, and store data

These read from input, use a stored secret, or call the Shopify Admin API. For the Shopify one, turn on Needs Shopify data on the Settings tab and grant the matching permission. See Permissions and store data access and Creating and using secrets.

POST to a webhook, using a variable and a secretjavascript
export default async function (input, ctx) {
  // secrets.WEBHOOK_URL is set on the Secrets page; input.message comes from Flow.
  const res = await ctx.fetch(secrets.WEBHOOK_URL, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ text: input.message ?? 'Hello from Shopify Flow' }),
  });

  if (!res.ok) {
    throw new Error(`Webhook failed with status ${res.status}`);
  }

  return { delivered: true, status: res.status };
}
Read a product from Shopifyjavascript
export default async function (input, ctx) {
  // Needs "Needs Shopify data" + Read products.
  // input.productId is a GID like "gid://shopify/Product/123".
  const res = await ctx.shopify.graphql(
    `query GetProduct($id: ID!) {
      product(id: $id) {
        id
        title
        totalInventory
      }
    }`,
    { id: input.productId }
  );

  if (res.errors) {
    throw new Error('Shopify error: ' + JSON.stringify(res.errors));
  }

  return res.data.product;
}

Larger: real workflows

Query several records or make a change in the store. Both need Needs Shopify data on and the matching permission granted.

Summarise recent ordersjavascript
export default async function (input, ctx) {
  // Needs "Needs Shopify data" + Read orders.
  const first = Math.min(Math.max(parseInt(input.first ?? 10, 10) || 10, 1), 100);

  const res = await ctx.shopify.graphql(
    `query RecentOrders($first: Int!) {
      orders(first: $first, reverse: true, sortKey: CREATED_AT) {
        edges {
          node {
            id
            name
            currentTotalPriceSet { shopMoney { amount currencyCode } }
          }
        }
      }
    }`,
    { first }
  );

  if (res.errors) {
    throw new Error('Shopify error: ' + JSON.stringify(res.errors));
  }

  const orders = res.data.orders.edges.map((edge) => edge.node);
  let total = 0;
  let currency = null;
  for (const order of orders) {
    total += Number(order.currentTotalPriceSet?.shopMoney?.amount ?? 0);
    currency = currency ?? order.currentTotalPriceSet?.shopMoney?.currencyCode ?? null;
  }

  ctx.log(`Summed ${orders.length} orders: ${total.toFixed(2)} ${currency ?? ''}`);

  return {
    count: orders.length,
    total: Number(total.toFixed(2)),
    currency,
    orders,
  };
}
Tag a customer (a mutation)javascript
export default async function (input, ctx) {
  // Needs "Needs Shopify data" + Write customers.
  // input.customerId is a GID like "gid://shopify/Customer/123"; input.tag defaults to "vip".
  const tag = input.tag ?? 'vip';

  const res = await ctx.shopify.graphql(
    `mutation AddTag($id: ID!, $tags: [String!]!) {
      tagsAdd(id: $id, tags: $tags) {
        node { id }
        userErrors { field message }
      }
    }`,
    { id: input.customerId, tags: [tag] }
  );

  const errors = res.errors ?? res.data?.tagsAdd?.userErrors;
  if (errors && errors.length) {
    throw new Error('Tagging failed: ' + JSON.stringify(errors));
  }

  ctx.log(`Tagged ${input.customerId} with "${tag}"`);
  return { tagged: input.customerId, tag };
}