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.
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;
}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.
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 };
}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.
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,
};
}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 };
}
