Serve WebP Images from Squarespace with Cloudinary

In our previous post, we explored delivering Squarespace images via the Cloudinary CDN. Today, I’ll introduce a snippet that intercepts Squarespace’s ImageLoader to serve WebP images to supported browsers, while falling back to traditional formats for others.

If you're looking for a suitable alternative for other image CDNs, consider checking out ImageKit and Cloudimage related posts.

The post will explain the mechanism, and you can find the code at the bottom of the article.

Serve WebP Images from Squarespace

Serve WebP Images from Squarespace

The WebP Challenge

Squarespace supports only JPG, GIF, and PNG image formats natively. Modern formats like WebP are not supported out of the box. However, by leveraging Cloudinary's fetch URL, we can cache Squarespace images and serve them as WebP when possible. Unsupported browsers will still receive JPG or PNG versions.

To achieve this, you need to add the f_auto (Format = Auto) parameter to Cloudinary fetch URLs. This will allow Cloudinary to automatically use WebP for supported browsers. For instance:

Squarespace CDN Cloudinary CDN WebP Cloudinary CDN Squarespace original images View image JPG - 291 kB - 2500 x 1667 Cloudinary delivery images View image JPG - 291 kB - 2500 x 1667 Cloudinary Webp delivery images View image WebP - 155 kB - 2500 x 1667

The image on the WebP Cloudinary CDN will be delivered in WebP format if supported, reducing the file size by 47% compared to the JPG version (155 kB vs 291 kB).

Solution

The solution involves replacing the srcset attributes of image elements with Cloudinary fetch URLs. Depending on user preferences, you can either fetch only the largest variant and use Cloudinary’s resizing transformations for the other variants (100, 300, 500, 750, 1000, 1500, 2500) or use Squarespace image variants directly with escaped URL parameters.

Testing

By injecting the script into the Footer injection, you can observe the difference in image requests (notice the transferred size) in the Chrome Network tab. Most images will be served as WebP on supported browsers like Chrome and the total resources size is reduced

Let’s take a look on how the images are loaded when scroll down

Known Issues

While this method offers a significant improvement by delivering WebP images where supported, there are a few things to keep in mind.

First, the images delivered through Cloudinary aren't exactly the same as your original uploads. Squarespace preprocesses and resizes your images to a maximum width of 2500px, so what you end up with from Cloudinary is often the largest variant available.

Additionally, despite injecting the script on the DOMContentLoaded event, it might not be fast enough to replace all images immediately. Since image loading is handled asynchronously, you might still see some images in their original format from Squarespace CDN before the script has a chance to replace them.

Another point to consider is that Cloudinary server determines the file format using the f_auto parameter. Occasionally, you might notice that images are served in their original format rather than WebP.

Lastly, keep an eye on Cloudinary’s bandwidth usage. Although the free plan offers generous limits, monitoring your usage is important to ensure it meets your needs.

The Code

To get started, you'll need to customize a few variables in the provided code snippet. Here’s how you can do it:

1. Cloudinary Cloud Name (required)

Replace "cloud_name" with your actual Cloudinary cloud name.

const CLOUDINARY_CLOUD_NAME = "cloud_name";

2. Transformations

Specify the transformations you want to apply. The default settings include automatic format and quality adjustments, but you can modify them as needed. For more details, check out Cloudinary’s Image Transformations documentation.

const CLOUDINARY_TRANSFORMATIONS = "f_auto,q_auto"; // Default: f_auto (format=auto), q_auto (quality=auto)

3. Image Variants

Determine whether to use Squarespace's image variants or let Cloudinary handle resizing. If true, the code will use Squarespace’s variants. Set to false to use Cloudinary’s resizing parameters instead.

const USE_SQUARESPACE_VARIANTS = true;

4. Variant Size Limit

Set the maximum size for the image variants. This controls the maximum variant to be used within body width, as explain in the previous post. Options available are 100, 300, 500, 750, 1500, or 2500.

const LIMIT_VARIANT_SIZE = 1500;

5. Excluded Images

If you want to exclude certain images (like fullscreen banners or lightbox images), list their selectors here. This ensures that high-quality images are preserved where needed.

const EXCLUDED_IMAGES = [];

To activate the code on your site:

<!-- sqs:image-loader-helper -->
<script>
window.ImageLoaderInterceptor = window.ImageLoaderInterceptor || (function() {
    // Check if the script has already been executed
    if (window.ImageLoaderInterceptorExecuted) return;
    window.ImageLoaderInterceptorExecuted = true;

    document.addEventListener('DOMContentLoaded', function () {
        const CLOUDINARY_CLOUD_NAME = "cloud_name";
        const CLOUDINARY_TRANSFORMATIONS = "f_auto,q_auto"; // Default is f_auto, separate transformations by comma
        const USE_SQUARESPACE_VARIANTS = true; // Use Squarespace variant via escaped ?format={variant}
        const LIMIT_VARIANT_SIZE = 1500;
        const EXCLUDED_IMAGES = [
            ".section-background",
            ".gallery-fullscreen-slideshow-item",
            ".gallery-lightbox-outer-wrapper",
            ".yui3-lightbox2 .sqs-lightbox-slideshow"
        ];

        const validImageSelector = EXCLUDED_IMAGES.map(selector => `${selector} img`).join(', ');
        const validImages = document.querySelectorAll(`img[data-src]:not(${validImageSelector})`);
        Array.from(validImages).forEach((image) => {
            const src = image.dataset.src;
            const sizes = [100, 300, 500, 750, 1000, 1500, 2500];

            let srcSets = sizes.map(size => {
                // Limit the size to 1500, skip the 2500 variant		   	
                const actualSize = size === 2500 ? LIMIT_VARIANT_SIZE : size;
                const imageSrc = '';

                if (!CLOUDINARY_CLOUD_NAME) {
                    return `${src}?format=${actualSize}w`;
                } else {
                    let transformations = CLOUDINARY_TRANSFORMATIONS;
                    if (USE_SQUARESPACE_VARIANTS) {
                        return `https://res.cloudinary.com/${CLOUDINARY_CLOUD_NAME}/image/fetch/${transformations}/${src}%3Fformat%3D${actualSize}w`;
                    } else {
                        transformations += `,w_${actualSize}`;
                        return `https://res.cloudinary.com/${CLOUDINARY_CLOUD_NAME}/image/fetch/${transformations}/${src}`;
                    }

                }
            });
          
          	let overridenSrcSet = srcSets.map((src, index) => `${src} ${sizes[index]}w`).join(', ');

            // Skip override if image already load
            if (image.complete) {
              return;
            }
			
          	image.removeAttribute('src');
            image.setAttribute('srcset', overridenSrcSet);
          	image.setAttribute('src', srcSets.pop());
        });
    });
})();
</script>
<!-- /sqs:image-loader-helper -->

Room for Improvement

  • Quality Settings: The default quality setting is q_auto, but you can set an explicit value like q=80 to adjust the compression level.

  • Variant Selection: Improve variant selection by considering content columns. For example, smaller variants might be more suitable for images in multi-column galleries.

Conclusion

By integrating Cloudinary to serve WebP images from Squarespace, you can significantly improve your site's performance and visual appeal. This approach leverages Cloudinary’s on-the-fly transformations to deliver WebP images to supported browsers while maintaining the original formats for those that don't support WebP.

This solution not only optimizes image sizes—resulting in faster load times—but also automates the process of image format conversion, sparing you the hassle of manually re-uploading images. For best results, use this method for standard images, but remember to consider exceptions for high-quality images in banners, backgrounds, and lightboxes.

By applying these adjustments, you ensure a more efficient and engaging experience for your site visitors, without compromising on the quality or appearance of your images. For those exploring alternative solutions, ImageKit.io offers similar benefits for next-gen image formats and optimized delivery.

Previous
Previous

How to use Cloudimage.io to deliver Squarespace photos

Next
Next

Must-have lightbox features for landscape photography websites