Images and web beacons

Learn how to work with images, including web beacons, within an HTML email

Before you begin

The examples shown below are based on two key assumptions:

  1. That you have already create a basic automated test using our getting started guides.
  2. You have a chosen assertion library that you will use to test the values shown below.

How many images

The html.images property of a message contains an array of images. The length of this array corresponds to the number of images found within an email.

console.log(message.html.images.length) // 2
print(len(message.html.images)) # 2
System.out.println(message.html().images().size()); // 2
Console.WriteLine(message.Html.Images.Count); // 2
puts(message.html.images.length) # 2
print(count($message->html->images)); // 2
fmt.Println(len(message.Html.Images)) // 2

Each attachment contains both a src attribute, which contains the location of the image, as well as an alt attribute holding the alternative, text description of the image.

Remotely-hosted images

Emails will often contain many images that are hosted elsewhere, such as on your website or product. It is recommended to check that these images are accessible by your recipients.

All images should have an alternative text description, which can be checked using the alt attribute.

const image = message.html.images[0]
console.log(image.alt) // "Hot air balloon"
image = message.html.images[0]
print(image.alt) # "Hot air balloon"
Image image = message.html().images().get(0);
System.out.println(image.alt()); // "Hot air balloon"
var image = message.Html.Images[0];
Console.WriteLine(image.Alt); // "Hot air balloon"
image = message.html.images[0]
puts(image.alt) # "Hot air balloon"
$image = $message->html->images[0];
print($image->alt); // "Hot air balloon"
image := message.Html.Images[0]
fmt.Println(image.Alt) // "Hot air balloon"

In addition, to check that the image itself is accessible, you can use the src attribute to perform an HTTP request to that address.

const https = require('https')

// ...

const image = message.html.images[0]
console.log(image.src) // "https://example.com/s.png?abc123"

// Make an HTTP call to trigger the web beacon
https.get(image.src, r => console.log(r.statusCode)) // 200
import requests

# ...

const image = message.html.images[0]
print(image.src) # "https://example.com/s.png?abc123"

# Make an HTTP call to trigger the web beacon
response = requests.get(image.src)
print(response.status_code) # 200
Image image = message.html().images().get(0);
System.out.println(image.src()); // "https://example.com/s.png?abc123"

// Make an HTTP call to trigger the web beacon
var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder(URI.create(image.src())).build();
var response = client.send(request, null);
System.out.println(response.statusCode()); // 200
var image = message.Html.Images[0];

Console.WriteLine(image.Src); // "https://example.com/s.png?abc123"

// Make an HTTP call to trigger the web beacon
using (var client = new HttpClient()) {
  var result = await client.GetAsync(image.Src);
  Console.WriteLine(result.StatusCode); // 200
}
image = message.html.images[0]
puts(image.src) # "https://example.com/s.png?abc123"

# Make an HTTP call to trigger the web beacon
uri = URI(image.src)
Net::HTTP.start(uri.host, uri.port,
:use_ssl => uri.scheme == 'https') do |http|
request = Net::HTTP::Get.new uri

response = http.request request # Net::HTTPResponse object
puts(response.code) # 200
end
$image = $message->html->images[0];
print($image->src); // "https://example.com/s.png?abc123"

// Make an HTTP call to trigger the web beacon
$ch = curl_init($image->src);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_exec($ch);
$statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

print($statusCode); // 200
image := message.Html.Images[0]
fmt.Println(image.Src) // "https://example.com/s.png?abc123"

// Make an HTTP call to trigger the web beacon
resp, _ := http.Get(image.Src)
fmt.Println(resp.StatusCode) // 200

Web beacons

A web beacon is a small image that can be used to track whether an email has been opened by a recipient.

Because a web beacon is simply another form of remotely-hosted image, you can use the same code shown above to trigger an open email event.

Embedded images

When an image is embedded within the content of an email, its src attribute will contain a “content ID” (e.g. cid:ii_1435fadb31d523f6).

Where a content ID is present, the image itself will be attached to the email, and so can be access in the same way as any other attachment. Note that the contentId attribute of the attachment will match the value found in the src attribute, excluding the cid: prefix.

const embeddedImage = message.html.images[0]
console.log(embeddedImage.src) // "cid:ii_1435fadb31d523f6"
console.log(embeddedImage.alt) // "Hot air balloon"
embedded_image = message.html.images[0]
print(embedded_image.src) # "cid:ii_1435fadb31d523f6"
print(embedded_image.alt) # "Hot air balloon"
Image embeddedImage = message.html().images().get(0);
System.out.println(embeddedImage.src()); // "cid:ii_1435fadb31d523f6"
System.out.println(embeddedImage.alt()); // "Hot air balloon"
var embeddedImage = message.Html.Images[0];
Console.WriteLine(embeddedImage.Src); // "cid:ii_1435fadb31d523f6"
Console.WriteLine(embeddedImage.Alt); // "Hot air balloon"
embedded_image = message.html.images[0]
puts(embedded_image.src) # "cid:ii_1435fadb31d523f6"
puts(embedded_image.alt) # "Hot air balloon"
$embeddedImage = $message->html->images[0];
print($embeddedImage->src); // "cid:ii_1435fadb31d523f6"
print($embeddedImage->alt); // "Hot air balloon"
embeddedImage := message.Html.Images[0]
fmt.Println(embeddedImage.Src) // "cid:ii_1435fadb31d523f6"
fmt.Println(embeddedImage.Alt) // "Hot air balloon"