Welcome to Shopify Image Technical SEO AI Image Optimizer tool.
WARNING: Before you make any changes to your production Shopify store, please don't. Instead, create a staging Shopify store and advance to making changes with these scripts there instead. After you are satisfied with the results, you can push your staging store to production.
This Optimizer will:
- Query products from your Shopify Store saving the IDS, handles, image URLs (for the product, not its variants), and placement of the image. Save into a CSV.
- Download all your images from said URLs and shard them using the unique product handles that your shopify store uses.
- Resize, compress, and covert the images to webp format.
- Make calls to Google Gemini API and figure out what's in each image with a custom prompt. Rename your images according to what's in them, adhering to technical SEO practices.
- Re-upload the images by replacing the previous ones with the correct product image placement from Shopify. While uploading, it will also use the file name to generate the Alt Text for the product image. Looking to use Gemini in this step as well in order to generate the ALT text.
Video run through can be found here: #Shopify #AI Product Images #SEO Optimizer - Google Gemini, Shopify GraphQL, #BASH
DISCLAIMER: This source code is to be used AS IS. While I have personally ran this in 2 different production Shopify Stores and replaced over 500 images, I'm still not sure what could go wrong while running the image replacement script.
My suggestion is to first run the image replacement script for 10 prodcuts at the time, checking if anything has gone wrong with your products, and then letting it run for a greater amount of products at the time. For example, I did batches of 20 at first, and once I saw it was replacing images correctly, I let it run until it finished all the 500+ images.
- The first thing we'll do is download the products in your Shopify Store into a CSV file.
- Grab your shop URL and API Key from your Shopify App.
- Replace the SHOPIFY_STORE and ADMIN_API_TOKEN values in the `utility.sh` file.
- Now you can run `extract_images_urls.sh` script.
- This will download all the required product information into a CSV file named 'image_urls.txt'.
NOTE: If you want to optimize products starting from a specific product ID instead of all of your products, then simply change the FROM_ID variable to the product ID you want to start from. This will download products starting FROM that ID to the latest one you created. Currently, the script does not handle dates, instead it uses IDs to specify which products will get processed. In other words, updated products will not get processed if their ID is less than the specified FROM_ID.
You can watch this VIDEO if you're wondering how to change the FROM_ID and how the product image saving process works overall.
- Now we can download the Images from the image_urls.txt file into a local folder from the Shopify CDN.
- To achieve this, we'll use the download_product_images.sh shell script.
- It will create the downloaded_images folder, and download the images from the Shopify CDN using the wget tool.
- Once downloaded, it will store each image into its respective folder dictated by the ${ProductHandle}/${ImagePlacement}/${FileName} directory scheme.
- Note that Product Handles cannot be duplicated. Therefore, we use Product Handles to shard the downloaded_images folders appropiately.
- To download the images, run the `./download_product_images.sh` command from your CLI and you will see the "Download complete! Images are saved in downloaded_images" if the images are downloaded correctly. This will take a while. You should see output on your console as images are being downloaded.
You can watch this VIDEO if you're wondering how the product image download process works.
-
Before we upload the images through the Gemini API to get the file names, let's compress them, resize them, and convert them to webp. This will not only optimize the images for the best web performance, it will also reduce the payload on the Gemini API calls.
ALERT: If your images are not resized and you are trying to upload large images to the Gemini API you will get the following error: 'Argument list too long'. Maybe we can find a workaround for this in case you need to upload large images.
!!!WARNING!!!: You should manually backup the `downloaded_images` folder at this point to create a backup of your original Shopify Store Images.
- Once you created your backup from the downloaded_images folder, you can take a look at the current hard-coded settings for image resizing and compression. Opening the image_resize.sh script will allow you to customize the MAX_WIDTH, MAX_HEIGHT, MAX_SIZE, and WEBP_QUALITY variable thresholds.
- Once you are satisfied with the thresholds, run the image_resize.sh script.
- This will run the `magick` command on each image and reduce their size if they are above the thresholds (MAX_WIDTH, MAX_HEIGHT, MAX_SIZE), using MAX_WIDTH and MAX_HEIGHT as dimension limits for your images.
- It will also run `magick` command on each image to compress and convert the images to webp format using the WEBP_QUALITY settings.
You can watch this VIDEO to see how the images are compressed and resized.
- Now it's time to rename the downloaded images using the `rename_images.sh` script. This will rename your image files so that they're named according to what's in the image itself.
- To do this, we'll use the Gemini API, prompt it to analyze the image and rename the file according to the prompt plus some pre-defined text that we'll hardcode in order to match your Shopify's store's targeted SEO keywords.
- What you'll need to make this happen is the following:
- Gemini Config:
- API KEY from Google Gemini. Get that from Google Gemini's official API dashboard..
- Prompt for the Gemini API; since in the demo here I was dealing with perfumes, my prompt was: "Analyze the image and tell me the **exact full name of the perfume** in the image. If there is no perfume, respond with '$NO_PRODUCT_STRING'."
- REMINDER: You can get as specific as you want with these prompts, however, you will have to remember that specificity means spending more tokens. More tokens means that you might be running out of tokens in your Google Gemini API requests which will disrupt your script. You will see an error message in the api_responses.log file which says something along "Resource Overloaded".
- Change the PRODUCT_IMAGE_APPEND variable to fit your use case. This variable will store what each image file name will get appended with. For example, my product images were for a Perfume shop who sells online and in the miami area. So my append text was "perfumes-online-and-in-miami". The script will then name images as so: "Shop-for-Yves-Saint-Laurent-MYSLF-Eau-de-Parfum-perfume-in-miami-and-online.webp". Notice that for the time being the "Shop-for-" portion of the file name is hardcoded. You can change that.
- Change the GEMINI_PROMPT variable to fit your use case. In the prompt, you must ALWAYS specify that the prompt returns the value for the variable 'NO_PRODUCT_STRING' when Gemini cannot find what you have specified.
- Finally, let's run the script by invoking `./rename_images.sh` from the command prompt. This will take a while. Notice the script sleeps every 15 requests to avoid hitting the APIs rate limit per minute. If any errors occur, they will be logged in the logs folder which the script creates. Look in your "downloaded-images", and you will see your images being renamed accordingly as the script runs.
- If your script stops midway, make sure to remove your already renamed files from the downloaded_folder, or, you could also re-run the script starting from the beginning... However you'll be taking up more tokens than needed. Maybe in the future we can make something better that moves the images to a new folder entirely after they are renamed.
- Another note is that if the product has no associted name and "NO_PRODUCT_STRING" is returned from the prompt, then the filename is derived from the product-handle.
You can watch this VIDEO to see how I rename the images using the Gemini 2.5 Flash Lite API. You can change the Gemini API that you're using, however, you might need to pay for their tokens.
- !!!WARNING!!!: If you haven't done so, make a backup of you downloaded_images folder at this point. If you need to re-downloaded all the original images again, then do so with the `download_product_images.sh` script. This next step is hihgly destructive and can have consequences on your Shopify Store.
- You will have update your correct API tokens from Shopify.
- and run the `./replace_remote_images.sh` script.
- This will start replacing the images from your Shopify Store products. New Images are uploaded and attached, and then the original is deleted. The process repeats for each image in the product, leaving the image order placements as they originally were.
- You can set the stop point for the script earlier so that you can check that your images are being uploaded correctly. Then you can continue by re-running the script, it'll pick up where you left off.
- The backup folder is there with the renamed and compressed images.
You can watch this VIDEO to see how the images are being replaced from the Shopify Store.