use Create Image Content
The hook combines image upload with content creation to generate user-generated content entries. Built on top of , it extends the basic upload functionality with content management features including titles, visibility controls, and unique IDs for sharing and discovery.
Visibility Options
The visibility parameter accepts an optional array of values:
: Makes content eligible for Shop's recommendation and discovery systems. Your content can appear in feeds and recommendations across the Shop app.: Enables shareable URLs for the content. Required if you want users to share content via direct links (generates a).- Both values:
- Maximum reach with content both discoverable in recommendations and shareable via links. - No values (
nullor[]): Content remains private within your Mini, not discoverable or shareable externally.
Use Cases
Choose visibility settings based on your content strategy:
- User reviews with photos: Use both
andfor maximum reach - Private user collections: Omit visibility or use empty array
- Shareable but not public: Use
only - Featured content: Use
to appear in recommendations
The hook handles both the image upload pipeline and content entity creation in a single operation, automatically associating content with your Mini and integrating with Shop's content systems.
You must run the setup CLI command before using this hook so the content can be associated with the Mini.
Anchor to useCreateImageContentuse Create Image Content()
- createImageContent(params: CreateImageContentParams) => Promise<{ data: Content; userErrors?: ContentCreateUserErrors[]; }>
Upload an image and create content.
- loadingboolean
Whether the content is being created.
UseCreateImageContentReturns
UseCreateImageContentReturns
- createImageContent
Upload an image and create content.
(params: CreateImageContentParams) => Promise<{ data: Content; userErrors?: ContentCreateUserErrors[]; }> - loading
Whether the content is being created.
boolean
interface UseCreateImageContentReturns {
/**
* Upload an image and create content.
*/
createImageContent: (
params: CreateImageContentParams
) => Promise<{data: Content; userErrors?: ContentCreateUserErrors[]}>
/**
* Whether the content is being created.
*/
loading: boolean
}CreateImageContentParams
- contentTitle
string - image
File - visibility
ContentVisibility[] | null
interface CreateImageContentParams {
image: File
contentTitle: string
visibility?: ContentVisibility[] | null
}ContentVisibility
'DISCOVERABLE' | 'LINKABLE'Content
- description
string | null - externalId
string | null - image
ContentImage - products
ContentProduct[] | null - publicId
string - shareableUrl
string | null - status
MinisContentStatus | null - title
string - visibility
ContentVisibility[]
export interface Content {
publicId: string
externalId?: string | null
image: ContentImage
title: string
description?: string | null
visibility: ContentVisibility[]
shareableUrl?: string | null
products?: ContentProduct[] | null
status?: MinisContentStatus | null
}ContentImage
- altText
string | null - height
number | null - id
string | null - thumbhash
string | null - url
string - width
number | null
export interface ContentImage {
id?: string | null
url: string
width?: number | null
height?: number | null
thumbhash?: string | null
altText?: string | null
}ContentProduct
- featuredImage
ContentImage | null - id
string - title
string
export interface ContentProduct {
id: string
title: string
featuredImage?: ContentImage | null
}MinisContentStatus
- PENDING
PENDING - READY
READY - REJECTED
REJECTED
export enum MinisContentStatus {
PENDING = 'PENDING',
READY = 'READY',
REJECTED = 'REJECTED',
}ContentCreateUserErrors
- code
ContentCreateUserErrorCode - message
string
export interface ContentCreateUserErrors {
code: ContentCreateUserErrorCode
message: string
}ContentCreateUserErrorCode
- DUPLICATE_EXTERNAL_ID
DUPLICATE_EXTERNAL_ID - INELIGIBLE_PRODUCTS
INELIGIBLE_PRODUCTS
export enum ContentCreateUserErrorCode {
DUPLICATE_EXTERNAL_ID = 'DUPLICATE_EXTERNAL_ID',
INELIGIBLE_PRODUCTS = 'INELIGIBLE_PRODUCTS',
}Examples
Example code
Default
import { useCreateImageContent, useImagePicker, Button, } from '@shopify/shop-minis-react' export default function MyComponent() { const {createImageContent, loading} = useCreateImageContent() const {openCamera, openGallery} = useImagePicker() const handleCameraCapture = async () => { try { const file = await openCamera() const result = await createImageContent({ image: file, contentTitle: 'Photo from camera', visibility: ['DISCOVERABLE', 'LINKABLE'], }) console.log({data: result.data, userErrors: result.userErrors}) } catch (error) { console.error('Failed to capture and upload image:', error) } } const handleGallerySelect = async () => { try { const file = await openGallery() const result = await createImageContent({ image: file, contentTitle: 'Photo from gallery', // Visibility options: // - ['DISCOVERABLE'] - Appears in Shop recommendations // - ['LINKABLE'] - Enables shareable URLs // - ['DISCOVERABLE', 'LINKABLE'] - Both features // - null or [] - Private within Mini only visibility: ['DISCOVERABLE', 'LINKABLE'], }) console.log({data: result.data, userErrors: result.userErrors}) } catch (error) { console.error('Failed to select and upload image:', error) } } return ( <> <Button onClick={handleCameraCapture} disabled={loading}> Take Photo and Upload </Button> <Button onClick={handleGallerySelect} disabled={loading}> Select from Gallery and Upload </Button> {loading && <p>Uploading image...</p>} </> ) }