//native
/**
* Add Products to Collection
* Manually add products (numeric IDs or GIDs) to a collection. The products are added as manual selections on the collection's own source, which is created if the collection has none yet.
*/
export async function main(
auth: RT.Shopify,
collection_id: string,
product_ids: string[]
) {
const id = collection_id.startsWith("gid://")
? collection_id
: `gid://shopify/Collection/${collection_id}`
const selections = product_ids.map((p) => ({
productId: p.startsWith("gid://") ? p : `gid://shopify/Product/${p}`,
}))
const url = `https://${auth.store_name}.myshopify.com/admin/api/2026-10/graphql.json`
const headers = {
"X-Shopify-Access-Token": auth.token,
"Content-Type": "application/json",
Accept: "application/json",
}
// 1. Find the collection's own (non-shareable) conditions source
const lookup = await fetch(url, {
method: "POST",
headers,
body: JSON.stringify({
query: `query ($id: ID!) { collection(id: $id) { title sources { id ... on CollectionConditionsSource { shareable } } } }`,
variables: { id },
}),
})
if (!lookup.ok) {
throw new Error(`${lookup.status} ${await lookup.text()}`)
}
const found = await lookup.json()
if (found.errors) {
throw new Error(JSON.stringify(found.errors))
}
const collection = found.data.collection
if (!collection) {
throw new Error(`Collection ${id} not found`)
}
const source = collection.sources.find(
(s: { shareable?: boolean }) => s.shareable === false
)
// 2. Add the products to that source, or create one holding them
const response = await fetch(url, {
method: "POST",
headers,
body: JSON.stringify({
query: `mutation ($collection: CollectionUpdateInput!) { collectionUpdate(collection: $collection) { collection { id legacyResourceId title productsCount { count } sources { id title } } userErrors { field message } } }`,
variables: {
collection: source
? {
id,
sourcesToUpdate: [
{
condition: {
id: source.id,
inclusion: { selectionsToAdd: selections },
},
},
],
}
: {
id,
sourcesToCreate: [
{
source: {
title: collection.title,
inclusion: { selections },
},
},
],
},
},
}),
})
if (!response.ok) {
throw new Error(`${response.status} ${await response.text()}`)
}
const { data, errors } = await response.json()
if (errors) {
throw new Error(JSON.stringify(errors))
}
if (data.collectionUpdate.userErrors.length) {
throw new Error(JSON.stringify(data.collectionUpdate.userErrors))
}
return data.collectionUpdate
}
Submitted by hugo989 3 hours ago