Building a Shoppable Videos mini
What will you learn?
In this guide, you'll learn how to do the following:
- Create a mini from a template.
- Set up an extension.
- Accept data from an entry point.
- Render a list of videos.
Prerequisites
This guide assumes that you have your test store set up and that you have already been onboarded to the Minis Platform.
Step 1: Use the Shoppable Videos template to create your mini
The CLI provides some templates for common use cases for a mini. That includes a template for mini that displays a feed of videos and products related to each video. We call this template "Shoppable Videos".
npm init @shopify/shop-mini@latest
Follow the prompts and choose the Shoppable Videos
template when asked.
Step 2: Set up your mini's extension
When you created your mini, you would have been prompted to create an extension. If you chose to create an extension, you may proceed to the next step. If you didn't, you can run the shop-minis create-extension
command to create one. We'll choose the Link
extension at the Product Page - Before Variants Picker
target for this example.
npx shop-minis create-extension
The Link
extension comes with a basic query input.graphql
that fetches the product's title. This data will be passed into the mini.
Step 3: Reading data from the extension
In your mini you can see the template code using the useMinisParams()
hook to get an extensionData
object which contains data that the extension has fetched.
const {extensionData} = useMinisParams<MyExtensionDataType>()
The useMinisParams
hook above is assigned a stub type to gives typing to extensionData
. We can replace it with the type generated from the extension's input query.
import {ProductVariantsRenderBeforeQueryData} from './targets/shop.product.variants.render-before/input.graphql'
// ...
const {extensionData} = useMinisParams<ProductVariantsRenderBeforeQueryData>()
Now we can access the shop's ID from the query.
Step 3: Fetch image URLs from a product metafield
Before we continue with this step, please follow the guide on metafields first. This step assumes that your products have a metafield with the key of videos
and the type list.url
.
Let's update our extension's query to fetch URLs of videos related to the product.
query ProductVariantsRenderBefore {
product {
id
title
videos: metafield(namespace: "app--12345--foo", key: "videos") {
value
}
}
}
Now lets start the mini dev server.
npm start
Navigate to the product screen to load your Link
extension and press on it to open the mini. We'll see that the extensionData
now contains a stringified array of image URLs from the metafield.
Step 4: Rendering a list of videos
In the template code we can see usage of a ShoppableVideos
component. The component is using data from a fixture variable shoppableVideosFixture
.
Now that we are able to query custom data from the product metafield, we can explore the shape of shoppableVideosFixture
to see what data we have to provide to the component. We can add more metafields if needed.
Eventually, we should be able to replace shoppableVideosFixture
with data from the query and / or other sources.
Step 5: Customizing your Shopable Videos mini
You can customize the look and feel of your Shoppable Videos mini by using the ShoppableVideos
component's props.
You can find the full list of props here: ShoppableVideosProps.
Example
// ...
<ShoppableVideos
items={shoppableVideos}
shopId={shopId}
fetchMore={fetchMore}
renderItem={({item}) => (
<View>
<CustomVideoHeader />
<Video
source={{uri: item.videoUrl}}
style={{height, width: 'auto'}}
poster={item.fallbackImageUrl}
posterResizeMode="cover"
repeat
resizeMode="cover"
paused={false}
progressUpdateInterval={10}
muted
ignoreSilentSwitch="ignore"
testID="video"
/>
<CustomVideoFooter />
</View>
)}
/>
// ...
// ...
<ShoppableVideos
items={shoppableVideos}
shopId={shopId}
fetchMore={fetchMore}
renderMedia={({item}) => <CustomCarouselPost images={imageStack(item)} />}
/>
// ...
// ...
<ShoppableVideos
items={shoppableVideos}
shopId={shopId}
fetchMore={fetchMore}
renderMediaHeader={() => null}
/>
// ...
// ...
<ShoppableVideos
items={shoppableVideos}
shopId={shopId}
fetchMore={fetchMore}
renderMediaFooter={({item}) => (
<View>
<Pressable
onPress={() => setShowGift(!showGift)}
style={{
justifyContent: 'flex-end',
marginBottom: 20,
}}
>
<IconButton
name="gift"
onPress={() => setShowGift(!showGift)}
accessibilityLabel="products"
/>
</Pressable>
<RelatedProductsList
products={item.relatedProducts}
style={RELATED_PRODUCTS_LIST_STYLE}
shopId={shopId}
/>
{showGift ? (
<GiftBottomSheet
text='Use PROMO2023 to get 10% off your purchase'
/>
) : null}
</View>
)}
/>
// ...
We look forward to seeing what you build!