Associate images with products: productCreateMedia vs. productUpdateMedia vs. productCreateMedia

Topic summary

Issue: A developer using Shopify API version 2024-01 struggled to associate existing media/images with products. They were confused about which mutation to use since productAppendImages is deprecated, and the available options—productCreateMedia and productUpdateMedia—seemed designed for creating or updating media rather than simply linking existing media to products.

Key Challenge:

  • Media already existed in the system and didn’t need creation or modification
  • Initial attempts showed “Media associated successfully” messages, but images weren’t appearing in product listings
  • Uncertainty about the correct GraphQL mutation for this use case

Resolution:

  • The solution involved using the full media URL instead of just the media GID when calling productCreateMedia
  • Developer created a helper function get_media_url() to fetch the complete URL from the media ID
  • Modified associate_media_with_product() to pass the full URL as originalSource in the mutation
  • After this change, product images displayed correctly in product listings

Code approach: Query the media node to retrieve the full image URL, then use productCreateMedia mutation with originalSource parameter containing that URL.

Summarized with AI on November 8. AI used: claude-sonnet-4-5-20250929.

SOLUTION: The solution was using the full url rather than only the image gid. Now, my product image shows within the product listing.

def get_media_url(media_id):
query = “”"
query getMediaUrl($id: ID!) {
node(id: $id) {
… on MediaImage {
image {
url
}
}
}
}
“”"
variables = {
“id”: media_id
}
response = requests.post(
graphql_endpoint,
json={“query”: query, “variables”: variables},
headers={“X-Shopify-Access-Token”: access_token},
)
result = response.json()
if ‘data’ in result and ‘node’ in result[‘data’] and ‘image’ in result[‘data’][‘node’]:
return result[‘data’][‘node’][‘image’][‘url’]
return None

def associate_media_with_product(product_id, media_id):
media_url = get_media_url(media_id)
if not media_url:
print(f"Failed to get URL for media {media_id}")
return None

mutation = “”"
mutation productCreateMedia($productId: ID!, $media: [CreateMediaInput!]!) {
productCreateMedia(productId: $productId, media: $media) {
media {
id
mediaContentType
}
product {
id
media(first: 10) {
edges {
node {
id
mediaContentType
}
}
}
}
mediaUserErrors {
field
message
code
}
}
}
“”"
variables = {
“productId”: product_id,
“media”: [
{
“mediaContentType”: “IMAGE”,
“originalSource”: media_url
}
]
}
response = requests.post(
graphql_endpoint,
json={“query”: mutation, “variables”: variables},
headers={“X-Shopify-Access-Token”: access_token},
)
return response.json()