Skip to main content

How to show variant color swatches using metafields

This guide will help you to show variant color swatches using metafields.

Let's divide this guide into two parts:

  1. How to configure variant metafields in Shopify.
  2. How to show variant color swatches in the app.

How to configure variant metafields in Shopify

  1. Go to your Shopify admin panel.
  2. Click on settings.
  3. Click on Custom Data.
  4. Select Variants
App Screenshot
  1. Click on Add definition.
App Screenshot
  1. Give the name,namespace and key.

  2. Select the type as file.

  3. Select images as file type.

App Screenshot
  1. Enable storefronts on access section.

  2. Click on Save.

  3. Go to Products → select a product → click on Edit on the variant.

App Screenshot
  1. Go to Metafields at the bottom of the page and you can see the metafield you created.
App Screenshot
  1. Click on Select image and select the image you want to show as a color swatch.

  2. Click on Save.

How to show variant color swatches in the app

  1. Add the following code in the activate function of the index.js file of the shopify package.

        import { addMetaFields } from './helper';

    export function activate(params) {
    addMetaFields();
    }
  2. You can get the extra metafields of the variant by using the addMetafieldsToVariant function of the metafieldsHelper.

    For example, you can create a helper file helper.js in the your theme and add the following code.

        import { metafieldsHelper } from '@appmaker-xyz/shopify';

    export function addMetaFields() {
    metafieldsHelper.addMetafieldsToVariant({
    namespace: 'custom',
    key: 'variant_color',
    });
    }
  3. Replace the variation block of product detail page.

    Variations block is used to show the product options in the product detail page. You can replace the variation block by adding the following code in the blocks/index.js file of the theme.

     import ShopifyProductOptions from '../components/product-variation-chooser';
    const blocks = [
    {
    name: 'appmaker/shopify-product-variation', // default variation block name
    View: ShopifyProductOptions, // replace the default variation block with the ShopifyProductOptions component
    },

    ];
    export { blocks };

    Write the component - components/prduct-variation-chooser.js. You can use the hook useProductOptions to get the product variation details. The metafield value of the variant is available in the variants object of the useProductOptions hook.

    You can use the getMediaImage function to get the image url of the metafield since you get the metafield value as a file id.

    Below is the sample code of the components/prduct-variation-chooser.js file. You can customize the code as per your requirement.

      import React, { useState, useEffect } from 'react';
    import { Pressable, StyleSheet, Text, View, ScrollView, Image } from 'react-native';
    import { useProductOptions } from '@appmaker-xyz/shopify';
    import { getMediaImage } from '../getmediaimage';

    const ProductVariationChooser = (props) => {
    const {
    variationOptions,
    setOption,
    selectedOptions,
    variants
    } = useProductOptions(props);

    const [variantImages, setVariantImages] = useState({});

    useEffect(() => {
    async function fetchImages() {
    const images = {};
    for (const variant of variants.edges) {
    const customVariantColor = variant.node.custom_variant_color?.value;
    if (customVariantColor) {
    const response = await getMediaImage(customVariantColor);
    const imageUrl = response?.data?.data?.nodes[0]?.image?.url;
    images[variant.node.title] = imageUrl;
    }
    }
    setVariantImages(images);
    }
    fetchImages();
    }, [variants]);

    return (
    <>
    {variationOptions.map((options) => {
    return (
    <ScrollView
    contentContainerStyle={styles.TextContainer}
    horizontal
    showsHorizontalScrollIndicator={false}
    key={options.key}
    >
    {options?.options?.map((item) => {
    const selectedOption = selectedOptions && selectedOptions[options?.key];
    const isSelected = selectedOption === item.value;

    // Find the variant based on the selected option
    const variant = variants.edges.find((edge) =>
    edge.node.selectedOptions.some(
    (option) =>
    option.name === options.key && option.value === item.value
    )
    );

    // Extract the custom_variant_color value from the corresponding variant
    const customVariantColor =
    variant && variant.node.custom_variant_color?.value;

    const customVariantImageUrl = variantImages[variant.node.title];

    return (
    <Pressable
    key={item.value}
    onPress={() => setOption(options.key, item.value)}
    >
    <View style={styles.variantItem}>
    {customVariantImageUrl && (
    <Image
    source={{ uri: customVariantImageUrl }}
    style={styles.variantImage}
    />
    )}
    <Text
    style={
    isSelected ? styles.selectedText : styles.titleText
    }
    >
    {item.label}
    </Text>
    </View>
    </Pressable>
    );
    })}
    </ScrollView>
    );
    })}
    </>
    );
    };

    const styles = StyleSheet.create({
    TextContainer: {
    fontFamily: 'Urbanist-Regular',
    },
    variantItem: {
    flexDirection: 'row',
    alignItems: 'center',
    marginRight: 16, // Add spacing between variants
    },
    variantImage: {
    width: 50,
    height: 50,
    marginRight: 8, // Add spacing between image and variant label
    },
    titleText: {
    color: 'black',
    borderWidth: 0.5,
    alignSelf: 'flex-start',
    paddingVertical: 14,
    paddingHorizontal: 22,
    textTransform: 'uppercase',
    letterSpacing: 4,
    fontSize: 16,
    fontFamily: 'Urbanist-Regular',
    },
    selectedText: {
    color: 'black',
    borderWidth: 0.5,
    alignSelf: 'flex-start',
    paddingVertical: 14,
    paddingHorizontal: 22,
    textTransform: 'uppercase',
    letterSpacing: 4,
    backgroundColor: '#F3FBFF',
    fontSize: 16,
    overflow: 'visible',
    fontFamily: 'Urbanist-Bold',
    },
    });

    export default ProductVariationChooser;
  4. Write the getMediaImage function in the getmediaimage.js file.

import { runDataSource } from "@appmaker-xyz/core";

export const getMediaImage = async(data)=>{
const dataSource = {
attributes: {},
source: "shopify",
};
const [response] = await runDataSource(
{
dataSource,
},
{
methodName: "gqlQuery",
params: {
query: `
query getMediaImages($ids: [ID!]!) {
nodes(ids: $ids) {
... on MediaImage {
alt
id
image {
url(transform:{maxHeight: 800, maxWidth: 800})
}
}
}
}
`,
variables: {
"ids": data
}
},
}
);
//console.log('response = ', response)
return response;
}

Result:

App Screenshot