Cloudinary Blog

Embed Images in Email Campaigns at Scale

Embed Images in Email Campaigns at Scale

tl;dr

Cloudinary is a powerful image hosting solution for email marketing campaigns of any size. With features such as advanced image optimization and on-the-fly image transformation, backed by a global CDN, Cloudinary provides the base for a seamless user experience in your email campaigns leading to increased conversion and performance.


We live in an era of information overload and attention is the real currency. Marketers are constantly looking for new ways to reach you, to advertise products and services that they think could improve your lives.

SnapChat and Instagram Stories are the newest channels marketers are trying to leverage. But there’s one tried-and-true channel that has proven its dominance for reaching your audience… and it’s none other than email marketing.

There are times when Marketing and IT must work together to implement multiple email marketing campaigns under a predefined budget.

Here’s the catch - our email database is really big. Large enough that any traditional email marketing software, such as Aweber or MailChimp, would cost at least five times more than what we had budgeted.

Clearly, we needed a more feasible solution.

If you are in a similar situation, your options include:

  • Engaging with a marketing automation system such as Marketo and HubSpot
  • Sending emails from your company’s email account

Let’s say you’ve implemented an email delivery solution. The next thing you need to figure out is where to host the images for the HTML used in your email.

Since we know that attention is the real currency, emails must:

  1. Be well-designed
  2. Carry a visual impact
  3. Look seamless across all devices - mobile, tablet and desktop
  4. Load fast

Here’s the deal - points one and two depend on your team’s creativity, and is subjective in nature.

What we can control are points three and four. And that’s where Cloudinary comes in.

Cloudinary is end-to-end, cloud-based solution that enables you to optimize, manipulate and transform images on-the-fly. It is designed for almost any service (product, website or app) that requires reliable image delivery.

Too complex? Think of Cloudinary as the perfect email image hosting solution.

I’ve personally used Cloudinary for my email marketing campaigns, and wanted to share how it could help you with yours.

While I’m not going to dive into all the features Cloudinary has to offer, I will discuss the features that:

  • Help improve user experience
  • Reduce resource consumption
  • Do a combination of both

Let’s take a look at these features, shall we?

On-the-Fly Image Optimization

We all need high-quality images for email marketing that load fast. One of the very basic, yet fundamentally important, features Cloudinary offers is on-the-fly image manipulation capabilities.

For starters, every image you upload is optimized and stored in Cloudinary’s servers. Only the optimized version of the image (which, by the way has negligible loss in quality) is served to the end user. This approach saves bandwidth costs for both you and the end user. Plus, the email loads faster on the user’s device (mobile or desktop), resulting in a better user experience.

On-Demand Image Resizing and Manipulation

Mobile screens are smaller, and therefore can benefit from use of smaller images. You don’t need a 1080p image for a email that’s primarily going to be viewed on a phone.

Whatever the device, Cloudinary enables me to configure the image resolution by defining the single parameter in the request URL. I don’t need to upload two (or more) versions of the image to Cloudinary. By changing just one parameter in the URL, I can quickly test which resolution works best. This is incredibly useful in A/B testing and designing emails.

For example, I use this simple command to resize the image:

Ruby:
Copy to clipboard
cl_image_tag("sample.jpg", :transformation=>[
  {:width=>300, :crop=>"scale"},
  {:opacity=>50}
  ])
PHP v1:
Copy to clipboard
cl_image_tag("sample.jpg", array("transformation"=>array(
  array("width"=>300, "crop"=>"scale"),
  array("opacity"=>50)
  )))
PHP v2:
Copy to clipboard
(new ImageTag('sample.jpg'))
  ->resize(Resize::scale()->width(300))
  ->adjust(Adjust::opacity(50));
Python:
Copy to clipboard
CloudinaryImage("sample.jpg").image(transformation=[
  {'width': 300, 'crop': "scale"},
  {'opacity': 50}
  ])
Node.js:
Copy to clipboard
cloudinary.image("sample.jpg", {transformation: [
  {width: 300, crop: "scale"},
  {opacity: 50}
  ]})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation()
  .width(300).crop("scale").chain()
  .opacity(50)).imageTag("sample.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('sample.jpg', {transformation: [
  {width: 300, crop: "scale"},
  {opacity: 50}
  ]}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sample.jpg", {transformation: [
  {width: 300, crop: "scale"},
  {opacity: 50}
  ]})
React:
Copy to clipboard
<Image publicId="sample.jpg" >
  <Transformation width="300" crop="scale" />
  <Transformation opacity="50" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sample.jpg" >
  <cld-transformation width="300" crop="scale" />
  <cld-transformation opacity="50" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sample.jpg" >
  <cl-transformation width="300" crop="scale">
  </cl-transformation>
  <cl-transformation opacity="50">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Width(300).Crop("scale").Chain()
  .Opacity(50)).BuildImageTag("sample.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation()
  .width(300).crop("scale").chain()
  .opacity(50)).generate("sample.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation()
  .setWidth(300).setCrop("scale").chain()
  .setOpacity(50)).generate("sample.jpg")!, cloudinary: cloudinary)

The w_300 tells the Cloudinary API to resize the image to a width of 300px. The height is adjusted automatically, thus maintaining the aspect ratio of the image.

There are tons of other image manipulation features mentioned in Cloudinary’s documentation.

Changing the Image, But Keeping the Same URL

This feature is a lifesaver when it comes to email marketing. Imagine spending hours crafting the perfect email, designing it over the course of a week. You embed the image in the email’s HTML file. Everything looks good.

On the day the campaign kicks off, you’re a bit nervous and after several checks, you press the send (or schedule) button. You grab a coffee and moments later you realize that the header image has a unexcusable, hair-raising typo. Think “End of Season Sale. Grab yourself a umbrella.”

If you’ve scheduled the campaign, there’s still hope. You can pause and fix the error. But what if your campaign is already being sent?

Here’s what I did:

  • Quickly fix the image.
  • Head over to Cloudinary’s dashboard and update the image.
  • Continue enjoying the coffee.

Winning the Battle Against Broken CSS Support

Here’s the deal - CSS support is shaky in most email clients. Some work, some don’t. There just isn’t seamless support for CSS in them.

When experimenting with Cloudinary, I found two particularly useful, on-the-fly image transformation features.

Opacity Transformation

The first feature is opacity transformation. In simple terms, this feature enables you to change the opacity of the image, on-the-fly.

If you’re using a background image in your email, opacity plays a major role in the contrast.

You might wonder - which email client does not support CSS opacity? You’d be surprised.

Note: MailChimp has this handy resource on CSS compatibility in various email clients.

The following email clients do not support CSS opacity:

  1. Gmail and Yahoo! web clients
  2. Microsoft Outlook 2000 - 2013 (desktop versions for Windows)
  3. Windows Live Mail (for those still on Windows 7)
  4. Gmail app for Android and iOS phones

The only desktop clients that do support CSS opacity are Apple Mail and Outlook 2013 for Mac.

This is where Cloudinary comes in.

In Cloudinary, you can easily manipulate the opacity of the image by adding the o_XX parameter. XX represents the digits of the opacity percentage.

For example, to display an image at 50 percent opacity, we add the parameter o_50 in the following URL:

Ruby:
Copy to clipboard
cl_image_tag("sample.jpg", :opacity=>50)
PHP v1:
Copy to clipboard
cl_image_tag("sample.jpg", array("opacity"=>50))
PHP v2:
Copy to clipboard
(new ImageTag('sample.jpg'))
  ->adjust(Adjust::opacity(50));
Python:
Copy to clipboard
CloudinaryImage("sample.jpg").image(opacity=50)
Node.js:
Copy to clipboard
cloudinary.image("sample.jpg", {opacity: 50})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().opacity(50)).imageTag("sample.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('sample.jpg', {opacity: 50}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sample.jpg", {opacity: 50})
React:
Copy to clipboard
<Image publicId="sample.jpg" >
  <Transformation opacity="50" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sample.jpg" >
  <cld-transformation opacity="50" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sample.jpg" >
  <cl-transformation opacity="50">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Opacity(50)).BuildImageTag("sample.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().opacity(50)).generate("sample.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setOpacity(50)).generate("sample.jpg")!, cloudinary: cloudinary)
Example of an image at 50 percent opacity, transformed dynamically

Now you can forget about the compatibility issues and design the newsletter!

CSS Sprite Generation

You can combine multiple logos into a single sprite image by using Cloudinary’s sprite-generation capabilities. This makes image management easier and gives better performance.

The sprite generation feature is useful in the email footers, where you want to showcase your clientele or partners. It helps establish trust in the product you’re marketing and uplifts your brand’s image.

For example, let’s say you’re a cloud-aggregator startup, specializing in managed CMS hosting. In other words you help setup and manage your client’s websites in cloud hosting companies.

In this role, you support the top four cloud hosting companies - AWS, Microsoft Azure, Google Cloud and IBM Cloud. You upload their logos in Cloudinary with a common tag - let’s say “supported_cloud”.

With Cloudinary’s sprite generation feature, you could display a single image that combines all the images with the supported_cloud tag. The, with a few CSS commands, you can display the logos in various sections of the footer.

This improves user experience by reducing network overhead and bypassing download limitations.

On-the-Fly Image Manipulation

Image manipulation comes in handy when you need to add a watermark to your images. A classic example would be screenshots of your SaaS dashboard, used in a drip email campaign.

And the best part? I don’t have to add the watermark to the image myself. All I need to do is configure the image URL and Cloudinary serves the watermarked version of the image to the end user.

Advanced Reporting

Cloudinary provides an intuitive dashboard that gives you a bird’s-eye view of your image stats. Screenshot of the Cloudinary Dashboard Report (Demo)

How many images were transformed on-the-fly? Storage quota consumed? Bandwidth used? These stats are presented in a beautiful graph. You can breakdown the report by month, or more granularly at a daily level. Interestingly I find that the bandwidth consumption correlates with the open-rate of my mailing lists.

Download API information in one-click from the Cloudinary dashboard

Note: Cloudinary displays your account details at the very top of the dashboard. Developers also can download the API access credentials in Python or YML in a single click.

Browser-based Image Format

This feature is, by far, one of my favorite things in Cloudinary. Browsers have evolved tremendously over the years. From being able to view simple text documents, to images and video. Today I am writing this article on Google Docs.

Each browser now supports a distinct type of image, that’s only applicable to, or supported by, that browser. For example, Google introduced the WebP image format back in 2010, which offers significant saving compared to JPEG. Only Google Chrome supports the WebP.

JPG Image
16.9KB JPG
WebP Automatic Image
6.9KB WebP

Similarly Microsoft announced JPEG-XR format in 2009, which offers better image compression than the original JPEG. It is supported in Internet Explorer 9 or above.

Here’s how Cloudinary creates the magic. With the Automatic Format Selection feature, Cloudinary automatically serves different formats of the image, based on the requesting browser. For example, it serves the WebP version of the image to Google Chrome users and JPEG-XR version of the image to Internet Explorer 9+ users. If the browser does not support these modern image formats, the default optimized JPEG is served.

Cloudinary does all of this on-the-fly, without us having to manually convert or upload multiple versions of the image. Simply add f_auto parameter to the requesting URL and the corresponding format would be served in the browser.

Ruby:
Copy to clipboard
cl_image_tag("sample.jpg", :width=>300, :opacity=>50, :crop=>"scale")
PHP v1:
Copy to clipboard
cl_image_tag("sample.jpg", array("width"=>300, "opacity"=>50, "crop"=>"scale"))
PHP v2:
Copy to clipboard
(new ImageTag('sample.jpg'))
  ->resize(Resize::scale()->width(300))
  ->adjust(Adjust::opacity(50));
Python:
Copy to clipboard
CloudinaryImage("sample.jpg").image(width=300, opacity=50, crop="scale")
Node.js:
Copy to clipboard
cloudinary.image("sample.jpg", {width: 300, opacity: 50, crop: "scale"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().width(300).opacity(50).crop("scale")).imageTag("sample.jpg");
JS:
Copy to clipboard
cloudinary.imageTag('sample.jpg', {width: 300, opacity: 50, crop: "scale"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("sample.jpg", {width: 300, opacity: 50, crop: "scale"})
React:
Copy to clipboard
<Image publicId="sample.jpg" >
  <Transformation width="300" opacity="50" crop="scale" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="sample.jpg" >
  <cld-transformation width="300" opacity="50" crop="scale" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="sample.jpg" >
  <cl-transformation width="300" opacity="50" crop="scale">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(300).Opacity(50).Crop("scale")).BuildImageTag("sample.jpg")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().width(300).opacity(50).crop("scale")).generate("sample.jpg");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setWidth(300).setOpacity(50).setCrop("scale")).generate("sample.jpg")!, cloudinary: cloudinary)
Using the Automatic Format Selection feature in Cloudinary, this same image would be served as WebP in Google Chrome or as JPEG in Firefox.

Browser-dependent image format rendering saves a lot of bandwidth when the email is viewed in a web browser, or when the HTML version of the email is viewed online.

Compress GIFs On-the-Fly

We started this article with the premise that attention is the most valuable currency in today’s world. When it comes to email marketing, getting someone to open the email depends on the quality of the subject line.

Our goal is to grab the user’s attention, right after he or she opens the email. That’s where an image comes in. A good header image can do wonders. What if we could take that one step further? What if we could crunch more relevant information into a single place, without requiring the user to scroll down?

That’s where videos come in. But unfortunately, videos are not supported in emails. That’s why you should use GIFs. You can keep the same information, and do away with the heavy size or the technical complexities of implementing the video.

Cloudinary supports animated GIFs, and with a few parameters, you can create winning emails!

Ruby:
Copy to clipboard
cl_image_tag("kitten_fighting.gif")
PHP v1:
Copy to clipboard
cl_image_tag("kitten_fighting.gif")
PHP v2:
Copy to clipboard
(new ImageTag('kitten_fighting.gif'));
Python:
Copy to clipboard
CloudinaryImage("kitten_fighting.gif").image()
Node.js:
Copy to clipboard
cloudinary.image("kitten_fighting.gif")
Java:
Copy to clipboard
cloudinary.url().imageTag("kitten_fighting.gif");
JS:
Copy to clipboard
cloudinary.imageTag('kitten_fighting.gif').toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("kitten_fighting.gif")
React:
Copy to clipboard
<Image publicId="kitten_fighting.gif" >

</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="kitten_fighting.gif" >

</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="kitten_fighting.gif" >

</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.BuildImageTag("kitten_fighting.gif")
Android:
Copy to clipboard
MediaManager.get().url().generate("kitten_fighting.gif");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().generate("kitten_fighting.gif")!, cloudinary: cloudinary)
Animated GIF served by Cloudinary

You can apply almost all the transformation effects to the GIFs (plus a few special ones). In our example, let’s serve the browser optimized format of the GIF.

Consider the following URL:

Ruby:
Copy to clipboard
cl_image_tag("kitten_fighting.gif", :fetch_format=>:auto)
PHP v1:
Copy to clipboard
cl_image_tag("kitten_fighting.gif", array("fetch_format"=>"auto"))
PHP v2:
Copy to clipboard
(new ImageTag('kitten_fighting'))
  ->delivery(Delivery::format(Format::auto()));
Python:
Copy to clipboard
CloudinaryImage("kitten_fighting.gif").image(fetch_format="auto")
Node.js:
Copy to clipboard
cloudinary.image("kitten_fighting.gif", {fetch_format: "auto"})
Java:
Copy to clipboard
cloudinary.url().transformation(new Transformation().fetchFormat("auto")).imageTag("kitten_fighting.gif");
JS:
Copy to clipboard
cloudinary.imageTag('kitten_fighting.gif', {fetchFormat: "auto"}).toHtml();
jQuery:
Copy to clipboard
$.cloudinary.image("kitten_fighting.gif", {fetch_format: "auto"})
React:
Copy to clipboard
<Image publicId="kitten_fighting.gif" >
  <Transformation fetchFormat="auto" />
</Image>
Vue.js:
Copy to clipboard
<cld-image publicId="kitten_fighting.gif" >
  <cld-transformation fetchFormat="auto" />
</cld-image>
Angular:
Copy to clipboard
<cl-image public-id="kitten_fighting.gif" >
  <cl-transformation fetch-format="auto">
  </cl-transformation>
</cl-image>
.NET:
Copy to clipboard
cloudinary.Api.UrlImgUp.Transform(new Transformation().FetchFormat("auto")).BuildImageTag("kitten_fighting.gif")
Android:
Copy to clipboard
MediaManager.get().url().transformation(new Transformation().fetchFormat("auto")).generate("kitten_fighting.gif");
iOS:
Copy to clipboard
imageView.cldSetImage(cloudinary.createUrl().setTransformation(CLDTransformation().setFetchFormat("auto")).generate("kitten_fighting.gif")!, cloudinary: cloudinary)

If you’re in Google Chrome or Opera, the f_auto parameter would have converted the GIF into an animated WebP file.

The Round-Up

Here’s a quick round-up of what we’ve covered so far:

  • Cloudinary automatically optimizes all the images on-the-fly.
  • You can resize and apply other on-demand transformation effects to your images.
  • You can change the image, while retaining the same URL.
  • Cloudinary’s opacity transformation and sprite generation features enables you to seamlessly design email campaigns that looks the same across all clients.
  • With on-the-fly image manipulation, you can generate watermarked versions of images, which are excellent to prevent email spams.
  • Cloudinary’s advanced analytics and reporting enables you to track your usage at all times.
  • Browser-based image format reporting delivers the image in the most optimal format, that is supported by the web browser.
  • Cloudinary also can optimize and apply various transformation effects to animated GIF images.

We’ve only begun to learn about Cloudinary’s amazing suite of image manipulation features. What we’ve discussed in the context of email marketing barely scratches the surface of the robust feature set offered by Cloudinary.

The good news is that all of these features would be applicable in multiple scenarios, in one way or the other. Did you know that Cloudinary serves these images via a global network of content delivery networks such as Akamai, Amazon Cloudfront and Fastly?

If you are looking to take your email marketing to the next level, Cloudinary is an excellent partner. The free Cloudinary account provides you enough quota to test the service and even possibly launch a trial email campaign.

Have you considered using Cloudinary in your email marketing programme? Let us know!

Sourav Kundu Sourav Kundu is an avid marketer with a passion for all things digital. From email marketing to app re-engagement campaigns, he loves putting on multiple hats during the workday. He's available for consultation over Twitter or his website.

Recent Blog Posts

Generate Waveform Images from Audio with Cloudinary

This is a reposting of an article written by David Walsh. Check out his blog HERE!
I've been working a lot with visualizations lately, which is a far cry from your normal webpage element interaction coding; you need advanced geometry knowledge, render and performance knowledge, and much more. It's been a great learning experience but it can be challenging and isn't always an interest of all web developers. That's why we use apps and services specializing in complex tasks like Cloudinary: we need it done quickly and by a tool written by an expert.

Read more
Make All Images on Your Website Responsive in 3 Easy Steps

Images are crucial to website performance, but most still don't implement responsive images. It’s not just about fitting an image on the screen, but also making the the image size relatively rational to the device. The srcset and sizes options, which are your best hit are hard to implement. Cloudinary provides an easier way, which we will discuss in this article.

Read more

The Future of Audio and Video on the Web

By Prosper Otemuyiwa
The Future of Audio and Video on the Web

Web sites and platforms are becoming increasingly media-rich. Today, approximately 62 percent of internet traffic is made up of images, with audio and video constituting a growing percentage of the bytes.

Read more
Build the Back-End For Your Own Instagram-style App with Cloudinary

Github Repo

Managing media files (processing, storage and manipulation) is one of the biggest challenges we encounter as practical developers. These challenges include:

A great service called Cloudinary can help us overcome many of these challenges. Together with Cloudinary, let's work on solutions to these challenges and hopefully have a simpler mental model towards media management.

Read more

Build A Miniflix in 10 Minutes

By Prosper Otemuyiwa
Build A Miniflix in 10 Minutes

Developers are constantly faced with challenges of building complex products every single day. And there are constraints on the time needed to build out the features of these products.

Engineering and Product managers want to beat deadlines for projects daily. CEOs want to roll out new products as fast as possible. Entrepreneurs need their MVPs like yesterday. With this in mind, what should developers do?

Read more

Your Web Image is Unnecessarily Bloated

By Christian Nwamba
Your Web Image is Unnecessarily Bloated

Images make up a majority of web content.But a lot of websites and applications that we browse aren’t always delivering the most optimal image format, size, quality and dimension.. . .

As a developer, it seems inefficient to serve a 2000kb JPEG image when we could compress images to optimize the performance without degrading the visual quality.

Read more