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:
cl_image_tag("sample.jpg", :transformation=>[
  {:width=>300, :crop=>"scale"},
  {:opacity=>50}
  ])
PHP:
cl_image_tag("sample.jpg", array("transformation"=>array(
  array("width"=>300, "crop"=>"scale"),
  array("opacity"=>50)
  )))
Python:
CloudinaryImage("sample.jpg").image(transformation=[
  {"width": 300, "crop": "scale"},
  {"opacity": 50}
  ])
Node.js:
cloudinary.image("sample.jpg", {transformation: [
  {width: 300, crop: "scale"},
  {opacity: 50}
  ]})
Java:
cloudinary.url().transformation(new Transformation()
  .width(300).crop("scale").chain()
  .opacity(50)).imageTag("sample.jpg")
JS:
cl.imageTag('sample.jpg', {transformation: [
  {width: 300, crop: "scale"},
  {opacity: 50}
  ]}).toHtml();
jQuery:
$.cloudinary.image("sample.jpg", {transformation: [
  {width: 300, crop: "scale"},
  {opacity: 50}
  ]})
React:
<Image publicId="sample.jpg" >
  <Transformation width="300" crop="scale" />
  <Transformation opacity="50" />
</Image>
Angular:
<cl-image public-id="sample.jpg" >
  <cl-transformation width="300" crop="scale">
  </cl-transformation>
  <cl-transformation opacity="50">
  </cl-transformation>
</cl-image>
.Net:
cloudinary.Api.UrlImgUp.Transform(new Transformation()
  .Width(300).Crop("scale").Chain()
  .Opacity(50)).BuildImageTag("sample.jpg")
Android:
MediaManager.get().url().transformation(new Transformation()
  .width(300).crop("scale").chain()
  .opacity(50)).generate("sample.jpg")

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:
cl_image_tag("sample.jpg", :opacity=>50)
PHP:
cl_image_tag("sample.jpg", array("opacity"=>50))
Python:
CloudinaryImage("sample.jpg").image(opacity=50)
Node.js:
cloudinary.image("sample.jpg", {opacity: 50})
Java:
cloudinary.url().transformation(new Transformation().opacity(50)).imageTag("sample.jpg")
JS:
cl.imageTag('sample.jpg', {opacity: 50}).toHtml();
jQuery:
$.cloudinary.image("sample.jpg", {opacity: 50})
React:
<Image publicId="sample.jpg" >
  <Transformation opacity="50" />
</Image>
Angular:
<cl-image public-id="sample.jpg" >
  <cl-transformation opacity="50">
  </cl-transformation>
</cl-image>
.Net:
cloudinary.Api.UrlImgUp.Transform(new Transformation().Opacity(50)).BuildImageTag("sample.jpg")
Android:
MediaManager.get().url().transformation(new Transformation().opacity(50)).generate("sample.jpg")
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:
cl_image_tag("sample.jpg", :width=>300, :opacity=>50, :crop=>"scale")
PHP:
cl_image_tag("sample.jpg", array("width"=>300, "opacity"=>50, "crop"=>"scale"))
Python:
CloudinaryImage("sample.jpg").image(width=300, opacity=50, crop="scale")
Node.js:
cloudinary.image("sample.jpg", {width: 300, opacity: 50, crop: "scale"})
Java:
cloudinary.url().transformation(new Transformation().width(300).opacity(50).crop("scale")).imageTag("sample.jpg")
JS:
cl.imageTag('sample.jpg', {width: 300, opacity: 50, crop: "scale"}).toHtml();
jQuery:
$.cloudinary.image("sample.jpg", {width: 300, opacity: 50, crop: "scale"})
React:
<Image publicId="sample.jpg" >
  <Transformation width="300" opacity="50" crop="scale" />
</Image>
Angular:
<cl-image public-id="sample.jpg" >
  <cl-transformation width="300" opacity="50" crop="scale">
  </cl-transformation>
</cl-image>
.Net:
cloudinary.Api.UrlImgUp.Transform(new Transformation().Width(300).Opacity(50).Crop("scale")).BuildImageTag("sample.jpg")
Android:
MediaManager.get().url().transformation(new Transformation().width(300).opacity(50).crop("scale")).generate("sample.jpg")
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:
cl_image_tag("kitten_fighting.gif")
PHP:
cl_image_tag("kitten_fighting.gif")
Python:
CloudinaryImage("kitten_fighting.gif").image()
Node.js:
cloudinary.image("kitten_fighting.gif")
Java:
cloudinary.url().imageTag("kitten_fighting.gif")
JS:
cl.imageTag('kitten_fighting.gif').toHtml();
jQuery:
$.cloudinary.image("kitten_fighting.gif")
React:
<Image publicId="kitten_fighting.gif" >

</Image>
Angular:
<cl-image public-id="kitten_fighting.gif" >

</cl-image>
.Net:
cloudinary.Api.UrlImgUp.BuildImageTag("kitten_fighting.gif")
Android:
MediaManager.get().url().generate("kitten_fighting.gif")
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:
cl_image_tag("kitten_fighting.gif", :fetch_format=>:auto)
PHP:
cl_image_tag("kitten_fighting.gif", array("fetch_format"=>"auto"))
Python:
CloudinaryImage("kitten_fighting.gif").image(fetch_format="auto")
Node.js:
cloudinary.image("kitten_fighting.gif", {fetch_format: "auto"})
Java:
cloudinary.url().transformation(new Transformation().fetchFormat("auto")).imageTag("kitten_fighting.gif")
JS:
cl.imageTag('kitten_fighting.gif', {fetch_format: "auto"}).toHtml();
jQuery:
$.cloudinary.image("kitten_fighting.gif", {fetch_format: "auto"})
React:
<Image publicId="kitten_fighting.gif" >
  <Transformation fetch_format="auto" />
</Image>
Angular:
<cl-image public-id="kitten_fighting.gif" >
  <cl-transformation fetch_format="auto">
  </cl-transformation>
</cl-image>
.Net:
cloudinary.Api.UrlImgUp.Transform(new Transformation().FetchFormat("auto")).BuildImageTag("kitten_fighting.gif")
Android:
MediaManager.get().url().transformation(new Transformation().fetchFormat("auto")).generate("kitten_fighting.gif")

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

Offline First Masonry Grid Showcase with Vue

To keep your product revelant in the market, you should be building Progressive Web Apps (PWA). Consider these testimonies on conversion rates, provided by leading companies, such as Twitter, Forbes, AliExpress, Booking.com and others. This article doesn't go into background, history or principles surrounding PWA. Instead we want to show a practical approach to building a progressive web app using the Vue.js library.

Read more
Optimize Images: Novactive eZ Platform Cloudinary Plugin

At Novactive, we are always excited to use new technologies and/or to improve our favorite technologies with other ones when it makes sense for us, for our clients and for the community.

Our business is web technologies, and the most professional content management system (CMS) for us is eZ Platform (previously eZ Publish). That's why we love creating connectors to this CMS. Our most recent eZ project is an image management plugin using Cloudinary.

Read more
Are your website images ready to embrace the iPhone X notch?

The announcement of the iPhone 8, 8 plus and the iPhone X at the iPhone 10th anniversary Apple event on 12th September 2017, came with a massive buzz.

The iPhone X (pronounced "iPhone 10") has a 5.8-inch super retina screen, which stands out amongst other Apples, giving the machine the tagline “it is all screen”. A resolution of 2436 x 1125 is also featured, making it the highest resolution iPhone to date.

Read more

Image Optimization: Expert Roundup

By Gilad Maayan
Image Optimization: Expert Roundup

Unoptimized images can be incredible bottlenecks that turn an otherwise well-built web page into a slow loading, bloated one. With the ever-increasing percentage of users on mobile devices, properly sizing and optimizing images to provide a good mobile experience is even more important.

Read more