WooCommmerce Featured Image, Product Gallery and Variation Images, Bricks Builder

functions.php code.

bricks builder tag for single product.

this code gets the all images as a ul li list very simple implementation.

//	{product_image_list}
add_filter( 'bricks/dynamic_tags_list', 'register_product_image_list' );
function register_product_image_list( $tags ) {
    $tags[] = [
        'name'  => '{product_image_list}',
        'label' => 'Product Image List',
        'group' => 'Custom Tags',
    ];

    return $tags;
}

// 2. Render the custom tag
add_filter( 'bricks/dynamic_data/render_tag', 'render_product_image_list', 10, 3 );
function render_product_image_list( $tag, $post, $context = 'text' ) {
    // Stop if it's not our custom tag
    if ( $tag !== 'product_image_list' ) {
        return $tag;
    }

    // Ensure it's a WooCommerce product
    if ( 'product' !== $post->post_type ) {
        return 'Not a product.';
    }

    // Get the product object from the post
    $product = wc_get_product( $post->ID );

    // Ensure the product actually exists
    if ( ! $product ) {
        return 'Invalid product.';
    }

    // Prepare an array to store all image URLs
    $image_urls = [];

    // Get the main (featured) product image
    $featured_image_id  = $product->get_image_id();
    $featured_image_url = $featured_image_id ? wp_get_attachment_url( $featured_image_id ) : '';

    // If the product has a featured image, let's add it first
    if ( $featured_image_url ) {
        $image_urls[] = $featured_image_url;
    }

    // Get any additional gallery images (beyond the featured image)
    $gallery_image_ids = $product->get_gallery_image_ids();
    if ( ! empty( $gallery_image_ids ) ) {
        foreach ( $gallery_image_ids as $gallery_id ) {
            $gallery_image_url = wp_get_attachment_url( $gallery_id );
            if ( $gallery_image_url ) {
                $image_urls[] = $gallery_image_url;
            }
        }
    }

    // If it's a variable product, also collect the variation images
    if ( $product->is_type( 'variable' ) ) {
        $variations = $product->get_available_variations();
        $variation_image_urls = [];

        foreach ( $variations as $variation ) {
            // Get the variation product object
            $variation_product  = wc_get_product( $variation['variation_id'] );
            $variation_image_id = $variation_product ? $variation_product->get_image_id() : 0;

            // First, try the variation's featured image (if set)
            if ( $variation_image_id ) {
                $variation_image_urls[] = wp_get_attachment_url( $variation_image_id );
            }
            // If there's no featured image on the variation, try the variation's default image
            elseif ( ! empty( $variation['image']['src'] ) ) {
                $variation_image_urls[] = $variation['image']['src'];
            }
        }

        // Merge variation images with our main array
        $image_urls = array_merge( $image_urls, $variation_image_urls );
    }

    // Remove any duplicates (just in case)
    $image_urls = array_unique( $image_urls );

    // Build the HTML list of images
    if ( ! empty( $image_urls ) ) {
        $list_html = '<ul class="product-image-list">';

        foreach ( $image_urls as $url ) {
            $url = esc_url( $url );
            $list_html .= '<li><img src="' . $url . '" alt="Product Image"></li>';
        }

        $list_html .= '</ul>';

        return $list_html;
    }

    return 'No product images available.';
}

// 3. Replace the custom tag in content dynamically
add_filter( 'bricks/dynamic_data/render_content', 'render_product_image_list_in_content', 10, 3 );
function render_product_image_list_in_content( $content, $post, $context = 'text' ) {
    // Only proceed if our custom tag is found in the content
    if ( strpos( $content, '{product_image_list}' ) !== false ) {
        $product_image_list = render_product_image_list( 'product_image_list', $post, $context );
        // Replace the tag with the generated HTML
        $content = str_replace( '{product_image_list}', $product_image_list, $content );
    }

    return $content;
}

and here is the optional one you can choice what to show with this tag.

{product_image_list} for Featured Image + Gallery

{product_image_list:variations} for Featured Image + Variation images.

//	{product_image_list}
//	{product_image_list:variations}

add_filter( 'bricks/dynamic_tags_list', 'register_product_image_list' );
function register_product_image_list( $tags ) {
    // Tag for featured + gallery
    $tags[] = [
        'name'  => '{product_image_list}',
        'label' => 'Product Image List (Featured + Gallery)',
        'group' => 'Custom Tags',
    ];
    // Tag for featured + variations
    $tags[] = [
        'name'  => '{product_image_list:variations}',
        'label' => 'Product Image List (Featured + Variations)',
        'group' => 'Custom Tags',
    ];

    return $tags;
}

// 2. Render the custom tag
add_filter( 'bricks/dynamic_data/render_tag', 'render_product_image_list', 10, 3 );
function render_product_image_list( $tag, $post, $context = 'text' ) {
    // Stop if it's not our custom tag
    // (i.e. if it's neither {product_image_list} nor {product_image_list:variations})
    if ( $tag !== 'product_image_list' && $tag !== 'product_image_list:variations' ) {
        return $tag;
    }

    // Ensure it's a WooCommerce product
    if ( 'product' !== $post->post_type ) {
        return 'Not a product.';
    }

    // Get the product object from the post
    $product = wc_get_product( $post->ID );

    // Ensure the product actually exists
    if ( ! $product ) {
        return 'Invalid product.';
    }

    // Prepare an array to store all image URLs
    $image_urls = [];

    // Get the main (featured) product image
    $featured_image_id  = $product->get_image_id();
    $featured_image_url = $featured_image_id ? wp_get_attachment_url( $featured_image_id ) : '';

    // If the product has a featured image, let's add it first
    if ( $featured_image_url ) {
        $image_urls[] = $featured_image_url;
    }

    // If the user used {product_image_list} (no variations), include the gallery images
    if ( $tag === 'product_image_list' ) {
        // Get any additional gallery images (beyond the featured image)
        $gallery_image_ids = $product->get_gallery_image_ids();
        if ( ! empty( $gallery_image_ids ) ) {
            foreach ( $gallery_image_ids as $gallery_id ) {
                $gallery_image_url = wp_get_attachment_url( $gallery_id );
                if ( $gallery_image_url ) {
                    $image_urls[] = $gallery_image_url;
                }
            }
        }
    }

    // If the user used {product_image_list:variations} and the product is variable, collect variation images
    if ( $tag === 'product_image_list:variations' && $product->is_type( 'variable' ) ) {
        $variations = $product->get_available_variations();
        $variation_image_urls = [];

        foreach ( $variations as $variation ) {
            // Get the variation product object
            $variation_product  = wc_get_product( $variation['variation_id'] );
            $variation_image_id = $variation_product ? $variation_product->get_image_id() : 0;

            // First, try the variation's featured image (if set)
            if ( $variation_image_id ) {
                $variation_image_urls[] = wp_get_attachment_url( $variation_image_id );
            }
            // If there's no featured image on the variation, try the variation's default image
            elseif ( ! empty( $variation['image']['src'] ) ) {
                $variation_image_urls[] = $variation['image']['src'];
            }
        }

        // Merge variation images with our main array
        $image_urls = array_merge( $image_urls, $variation_image_urls );
    }

    // Remove any duplicates (just in case)
    $image_urls = array_unique( $image_urls );

    // Build the HTML list of images
    if ( ! empty( $image_urls ) ) {
        $list_html = '<ul class="product-image-list">';

        foreach ( $image_urls as $url ) {
            $url = esc_url( $url );
            $list_html .= '<li><img src="' . $url . '" alt="Product Image"></li>';
        }

        $list_html .= '</ul>';

        return $list_html;
    }

    return 'No product images available.';
}

// 3. Replace the custom tags in content dynamically
add_filter( 'bricks/dynamic_data/render_content', 'render_product_image_list_in_content', 10, 3 );
function render_product_image_list_in_content( $content, $post, $context = 'text' ) {

    // First replace {product_image_list:variations} (so it doesn't get overshadowed by {product_image_list})
    if ( strpos( $content, '{product_image_list:variations}' ) !== false ) {
        $product_image_list_variations = render_product_image_list( 'product_image_list:variations', $post, $context );
        $content = str_replace( '{product_image_list:variations}', $product_image_list_variations, $content );
    }

    // Then replace {product_image_list}
    if ( strpos( $content, '{product_image_list}' ) !== false ) {
        $product_image_list = render_product_image_list( 'product_image_list', $post, $context );
        $content = str_replace( '{product_image_list}', $product_image_list, $content );
    }

    return $content;
}




and here is another alternative this has some style fixes and add auto .active class to the thumbnails depending on active big image on right so you can style it with css easily.

same as before {product_image_list_gallery} gets the featured+gallery

{product_image_list_gallery:variations} gets the featured+variation images



//   {product_image_list_gallery}		{product_image_list_gallery:variations}

add_filter( 'bricks/dynamic_tags_list', 'register_product_image_list_gallery' );
function register_product_image_list_gallery( $tags ) {
    // Tag for featured + gallery
    $tags[] = [
        'name'  => '{product_image_list_gallery}',
        'label' => 'Product Image List Gallery (Featured + Gallery)',
        'group' => 'Custom Tags',
    ];
    // Tag for featured + variations
    $tags[] = [
        'name'  => '{product_image_list_gallery:variations}',
        'label' => 'Product Image List Gallery (Featured + Variations)',
        'group' => 'Custom Tags',
    ];

    return $tags;
}

// 2. Render the custom tag
add_filter( 'bricks/dynamic_data/render_tag', 'render_product_image_list_gallery', 10, 3 );
function render_product_image_list_gallery( $tag, $post, $context = 'text' ) {
    // Stop if it's not our custom tag
    if ( $tag !== 'product_image_list_gallery' && $tag !== 'product_image_list_gallery:variations' ) {
        return $tag;
    }

    // Ensure it's a WooCommerce product
    if ( 'product' !== $post->post_type ) {
        return 'Not a product.';
    }

    // Get the product object
    $product = wc_get_product( $post->ID );
    if ( ! $product ) {
        return 'Invalid product.';
    }

    // Prepare an array to store all image URLs
    $image_urls = [];

    // Get the main (featured) product image
    $featured_image_id  = $product->get_image_id();
    $featured_image_url = $featured_image_id ? wp_get_attachment_url( $featured_image_id ) : '';

    // If the product has a featured image, add it first
    if ( $featured_image_url ) {
        $image_urls[] = $featured_image_url;
    }

    // If the user used {product_image_list_gallery} (no variations), include the gallery images
    if ( $tag === 'product_image_list_gallery' ) {
        $gallery_image_ids = $product->get_gallery_image_ids();
        if ( ! empty( $gallery_image_ids ) ) {
            foreach ( $gallery_image_ids as $gallery_id ) {
                $gallery_image_url = wp_get_attachment_url( $gallery_id );
                if ( $gallery_image_url ) {
                    $image_urls[] = $gallery_image_url;
                }
            }
        }
    }

    // If the user used {product_image_list_gallery:variations} and the product is variable, collect variation images
    if ( $tag === 'product_image_list_gallery:variations' && $product->is_type( 'variable' ) ) {
        $variations = $product->get_available_variations();
        $variation_image_urls = [];

        foreach ( $variations as $variation ) {
            $variation_product  = wc_get_product( $variation['variation_id'] );
            $variation_image_id = $variation_product ? $variation_product->get_image_id() : 0;

            // Variation's featured image
            if ( $variation_image_id ) {
                $variation_image_urls[] = wp_get_attachment_url( $variation_image_id );
            }
            // Variation default image
            elseif ( ! empty( $variation['image']['src'] ) ) {
                $variation_image_urls[] = $variation['image']['src'];
            }
        }

        // Merge variation images
        $image_urls = array_merge( $image_urls, $variation_image_urls );
    }

    // Remove duplicates
    $image_urls = array_unique( $image_urls );

    // Build the simple gallery HTML (left thumbnails, right big image) if we have images
    if ( ! empty( $image_urls ) ) {
        // Re-index the array to easily get the first item
        $image_urls = array_values( $image_urls );
        $first_image_url = esc_url( $image_urls[0] );

        // Start building HTML
        $list_html  = '<div class="product-image-gallery" style="width:100%; display: flex; gap: 10px;">';

        // Unique class & function names based on product ID
        $thumbnail_wrapper_class = 'left-thumbnails-' . $post->ID;
        $update_function_name    = 'updateActiveThumbnail' . $post->ID;

        // Left thumbnails
        $list_html .= '<div class="' . $thumbnail_wrapper_class . '" style="width: 100px;">';
        $list_html .= '<ul style="list-style: none; margin: 0; padding: 0;">';

        foreach ( $image_urls as $index => $url ) {
            $url_escaped   = esc_url( $url );
            $active_class  = ( $index === 0 ) ? ' active' : ''; // The first thumbnail is active by default
            $list_html    .= '<li style="margin-bottom: 10px;">';
            $list_html    .= '<img 
                src="' . $url_escaped . '" 
                alt="Product Image" 
                class="thumb' . $active_class . '" 
                style="width: ; height: ; cursor:pointer;" 
                onclick="' . $update_function_name . '(this)" 
            />';
            $list_html    .= '</li>';
        }

        $list_html .= '</ul>';
        $list_html .= '</div>';

        // Right big image
        $list_html .= '<div class="right-big" style="width:auto; flex:1">';
        $list_html .= '<img 
            id="mainImage' . $post->ID . '" 
            src="' . $first_image_url . '" 
            alt="Product Image" 
            style="" 
        />';
        $list_html .= '</div>';

        // Close wrapper
        $list_html .= '</div>';

        // Inline JS to handle active class switching
        // Note: If you have multiple products on one page, each will have its own function 
        //       named uniquely by the product ID to avoid conflicts.
        $list_html .= '
            <script>
            function ' . $update_function_name . '(clickedImg) {
                // Update main image source
                document.getElementById("mainImage' . $post->ID . '").src = clickedImg.src;

                // Remove .active from all thumbnails
                var thumbnails = document.querySelectorAll(".' . $thumbnail_wrapper_class . ' img.thumb");
                thumbnails.forEach(function(img) {
                    img.classList.remove("active");
                });

                // Add .active to the clicked thumbnail
                clickedImg.classList.add("active");
            }
            </script>
        ';

        return $list_html;
    }

    return 'No product images available.';
}

// 3. Replace the custom tags in content dynamically
add_filter( 'bricks/dynamic_data/render_content', 'render_product_image_list_gallery_in_content', 10, 3 );
function render_product_image_list_gallery_in_content( $content, $post, $context = 'text' ) {

    // First replace {product_image_list_gallery:variations}
    if ( strpos( $content, '{product_image_list_gallery:variations}' ) !== false ) {
        $product_image_list_gallery_variations = render_product_image_list_gallery( 'product_image_list_gallery:variations', $post, $context );
        $content = str_replace( '{product_image_list_gallery:variations}', $product_image_list_gallery_variations, $content );
    }

    // Then replace {product_image_list_gallery}
    if ( strpos( $content, '{product_image_list_gallery}' ) !== false ) {
        $product_image_list_gallery = render_product_image_list_gallery( 'product_image_list_gallery', $post, $context );
        $content = str_replace( '{product_image_list_gallery}', $product_image_list_gallery, $content );
    }

    return $content;
}