SparkPost and PHP Frameworks: Scratching the Surface

PHP is one of the older languages used on the Web, created in the mid-nineties. Some environments are still stuck running PHP 3 while others are running the latest version. There’s been a lot of development around amazing PHP frameworks and tools in the last few years, and most of them come with easy ways to send mail. We recently broke down how we simplified our PHP library, but going with a native solution can still be easier sometimes. Here’s a quick breakdown of how to use SparkPost to send mail with some of the more popular PHP frameworks in the wild.

Plain ol’ PHP

Sometimes you just need to fire off a quick API call. All you need is a little cURL magic to do what you need. Check out this snippet for shooting off SparkPost requests.

🐘 + 🎶 = ❤️

Here at SparkPost we created a composer package to simplify using our API in all modern PHP environments. It’s quick to install and provides some “sugar” to smooth out some of the more confusing parts of the API. To keep our library as flexible as possible, we use PHP HTTP to let you bring your own request library. To use it we can require guzzlehttp/guzzle, the php-http/guzzle6-adapter, and the sparkpost/sparkpost library. Then we are good to go with the code below.

World of WordPress

Our very own Raju wrote a SparkPost plugin to use SparkPost as your email provider. It exposes key features like using templates, sending via SMTP or the API, and allows you to hook in at a ton of points to modify the email and settings on the fly. Plus, it’s easy to get started 😎


PHPMailer is probably the most popular way to send mail in PHP! It’s got a great API that makes it easy to plug any SMTP provider. Check out this simple example to get started with SparkPost quickly.


Laravel is a whole beast unto itself so I’ll just hit the main points. You can follow the official Laravel docs to get set up with the SparkPost mail driver. Once you’ve done that you can generate and send your mailables. Matt Stauffer did a solid write up on using SparkPost with Laravel which is worth checking out.


CodeIgniter provides a simple API to send mail. You can add the SMTP configuration in code or through config/email.php. Check out the example below to fire off a quick email.

Be sure to comment below or tweet us if you want us to go into more depth on any particular tool or if we missed your favorite framework 👋

—Avi, Software Engineer

10 Steps Great Deliverability Blog Footer

You might remember that last year we released the 2.0 version of the SparkPost PHP client library. We’ve talked about the evolution of our approach across all our client libraries, but I wanted to dive deeper into the PHP changes.


After 18 months of having our client libraries in the wild we’ve learned some important lessons. The biggest one was that abstraction is hard when you’re wrapping a living, growing API. With 16 API endpoints and more coming we were limiting our users and ourselves as our client libraries fell behind our API additions. We changed our mentality to focus on providing a thin layer of abstraction with some syntactic “sugar” to simplify the more complex areas of our API.

Using the PHP client library

In the new version we decided to let a single method drive all SparkPost requests. This lets you hit any API endpoint quickly and with a ton of flexibility.

In the 1.x version we did a good amount of property mapping. For example, to enable inline css you would set 'inlineCss' => true when you called $sparky->transmission->send. Now in the 2.x release, we simply pass along the data you provide, so to inline css you would set 'options' => [ 'inline_css' => true ] . While this might look more complex at first it actually makes it easier to use since you can now depend on our main API docs and quickly translate JSON into an associative array.

We also moved off of the deprecated egeloen/ivory-http-adapter to use php-http/httplug. This means you can continue to bring your own HTTP request library and adds the new ability to use promises in PHP.

How To Use It

We have a bunch of examples on how to use our new 2.x library in the github repo. Here’s a quick walk through on how to get going.

Installing & setup

First we need to pull the library from composer. If you don’t have that setup, check out their getting started page. (If you’re using a PHP version earlier than 5.6 or you can’t use composer you can still use our API with some simple cURL magic!)

We are going to use guzzle as our request library. You can use any of the httplug-supported clients.

Now that we have our dependencies we can set up the library. To run our code synchronously we’ll set async to false.

Building the transmission

Looking at the following transmission, we can see it’s almost identical to a regular SparkPost transmission. The difference is that we added a cc and bcc. This is that “sugar” I mentioned. The library will go through and format your cc and bcc recipients to fit the SparkPost API’s requirements.

And there you go! Your email is off!

To dig into the library, checkout the repo on GitHub, or come talk to our team in Slack. And if you find a bug (😱) submit an issue or a PR. Check back soon for an upcoming post on using SparkPost with some popular PHP frameworks.

Avi, Software Engineer

Dev Survival Guide Blog Footer

Segmenting audiences is a basic practice in email marketing. From super consumers to influencers, iPhone users to desktop holdouts, learning about your recipient’s preferences is clearly important. In these days of deep personalization, it’s also just nice to know a little more about your customer base. Luckily, this is a pretty easy job with SparkPost message events.

In this post, I’ll review the content of the User-Agent header, then walk through the process of receiving tracking events from SparkPost’s webhooks facility, parsing your recipient’s User-Agent headers, and using the results to build a simple but extensible report for tracking Operating System preferences. I’ll be using PHP for the example code in this article, but most of the concepts are transferrable to other languages.

SparkPost Webhook Engagement Events

SparkPost webhooks offer a low-latency way for your apps to receive detailed tracking events for your email traffic. We’ve written previously about how to use them and how they’re built, so you can read some background material if you need to.

We’ll be focusing on just the click event here. Each time a recipient clicks on a tracked link in your email, SparkPost generates a click event that you can receive by webhook. You can grab a sample click event directly from the SparkPost API here. The most interesting field is naturally msys.track_event.user_agent which contains the full User-Agent header sent by your recipient’s email client when they clicked the link.

Grokking The User Agent

Ok, so we can almost pick out the important details from that little blob of text. For the dedicated, there’s a specification but it’s a tough read. Broadly speaking, we can extract details about the user’s browser, OS, and “device” from the user agent string.

For example, from my own user agent:

…you can tell I’m an Android user with a Huawei Nexus 6P device (and that it’s bang up-to-date 😉 ).

Caveat: user agent spoofing

Some of you might be concerned about the information our user agent shares with the services we use. As is your right, you can use a browser plugin (Chrome, Firefox) or built-in browser dev tools to change your user agent string to something less revealing. Some services on the web will alter your experience based on your user agent though so it’s important to know the impact these tools might have on you.

Harvesting User Agents From SparkPost Tracking Events

Alright, enough theory. Let’s build out a little webhook service to receive, process, and stash user agent details for each click tracked through our SparkPost account.

First we’ll have to accept and decode a JSON-encoded POST request (omitting the necessary error handling boilerplate for brevity):

Then we’ll unpack each nested event structure into something more manageable:

Let’s retain just the click events (when we register our webhook with SparkPost later, we can also ask it to send only click events):

There’s a lot of detail in a single event. It might be a good idea to pare things down to just the fields we care about:

Now we can enrich our events with new information. We’ll parse the user agent string and extract the OS:

Note: not all user agent strings will contain the detail we want (or even make sense at all), so we label all odd-shaped clicks with “OS: unknown”.

Alright, now we have an array of events like this, containing only interesting fields and with an extra “os” field to boot:

Generating Report-Ready Summary Data

At this point, we could just list each event and call our report done. We’ve come to expect some summarization in our reports, to simplify the task of understanding. We’re interested in OS trends in our email recipients, which suggests that we should aggregate our results: collect summaries indexed by OS. Here’s a simple implementation that groups array elements by 1 or more field values to help with that:

Now we can group our events by OS and finally count the events in each group:

Now we have summaries like this:

That matches surprisingly well with the Google Charts pie chart data format. All that remains is to collect those summary records in our storage service of choice and render a report.

We could stop there, citing “exercise for the reader,” but I always find that frustrating. Instead, here’s a batteries-included implementation which stores click event summaries in PostgreSQL and renders a simple report using Google Charts. Here’s what that final chart looks like:

email recipient OS preferences user agent graph-1

An Exercise For The Reader

I know, I said I wouldn’t do this. Bear with me: if you were paying attention to the implementation steps above, you might have noticed several re-usable elements. Specifically, I drew a few filtering and reporting parameters out for re-use:

  • event type filters
  • event field filters
  • event “enrichment” functionality
  • aggregation/grouping fields

With minimal effort, you could add, filter on, and group the campaign_id  field to see OS preference broken down by email campaign. You could use it as a basis for updating your own user database from bounce events with type=bounce , fields=rcpt_to , bounce_class  and so on.

I hope this short walkthrough gave some practical insight on using SparkPost webhooks. With a little experimentation, the project could be made to fit into plenty of use cases and I’d be more than happy to accept contributions on that theme. If you’d like to talk about your own event processing needs, SparkPost webhooks, or anything else, come find us on Slack!

– Ewan

Top 10 Blogs: Our Year in Review

We’re finishing out the year with a roundup of our top 10 blogs from 2016. The Mandrill announcement in April impacted our community, and as a result our blog, in a big way. We’re recapping that along with other top posts on deliverability tips and email marketing best practices down below. As always, our ears are open, so if there’s a certain topic you’d like to see on the blog, leave us a comment, tweet us, or ping us in slack.

Without further ado, we give you the top 10 blogs of 2016:

#1 Mandrill Alternatives

It’s no surprise that our Mandrill alternative blogs dominated our top 10 list (5 out of our top 10). We responded in real-time to the Mandrill crisis, and our CEO even weighed in and made you a promise he intends to stick by for the long haul. The Mandrill incident also inspired us to create SendGrid and Mailgun migration guides, check them out when you have a chance.

Mandrill Template Migration top 10 blogs

#2 PHP

But beyond Mandrill, we also had some other top posts. Coming in second was using SparkPost in PHP. Believe it or not, many of you use PHP through our WordPress plugin.

PHP in SparkPost

#3 Advanced Email Templates

For developers who want to get the most out of SparkPost templating capabilities, this post was meant for you! In this straight-forward post, Chris Wilson makes sending email easy and gives you some pro tips along the way.


advanced email templates


#4 What Recruiters Look for in a Dev Candidate

Everyone wants to know how to interview well. In this post we told you about what four tech recruiters look for when hiring developer and engineering candidates.

Recruiter for Dev Candidate

#5 Webhooks!

One of the most useful elements of SparkPost are our webhooks and in this post, Ewan Dennis walks you through the basics and beyond. Knowing what to expect functionally beyond the raw API spec is half the battle when consuming new data sources like SparkPost webhooks.

webhooks: beyond the basics

#6 Outlook and Hotmail Email Deliverability

The Outlook inbox is one of the major destinations for most email senders, especially those with large numbers of consumer subscribers. It also has a reputation for being somewhat tricky to get into. In this post, one of our deliverability experts, Tonya Gordon, shares what senders need to know in order to get the best Hotmail/Outlook deliverability and ensure their messages reach the inbox.

#7 Announcing Subaccounts!

Thanks to your feedback, the Mandrill event helped us expedite our release of subaccounts ahead of schedule. Our VP of Product told you about how we process your feedback and what’s available with subaccounts.

SparkPost #WeLoveDevelopers

#8 Are You an Email Rookie?

Sometimes you need to go beyond a top 10 list and in this case we did — 17 tips on how not to be labeled an email rookie. In this post we put together a list of common mistakes, with a heavy dose of snark, on how to avoid being labeled an email marketing rookie.

Email Marketing Rookie Kid Missing Steering Wheel

#9 Retail Marketing Stats You Need to Know

Do you know what the lowest e-commerce order generators are? In this post, we give you five tips and stats for mastering retail marketing. From social media, to mobile and beacon triggered emails.

Retail Marketing statistics mobile 2016

#10 Setting Up SparkPost as your SMTP Relay

You know you need to send email, but you don’t want to spend a lot of time or effort on it — you just want something that works out of the box. It’s not too much to ask! Many frameworks, languages, and tools come with SMTP support, but the last step is the most important – an SMTP server. In this post, we walk you through how to set up SparkPost as your SMTP Relay.

And that rounds out our Top 10 Blogs for 2016! Any industry trends or topics you think were under-represented? Leave us a comment below, or tweet us!



I have an old-school pocket dictionary at home (literally, old school… it’s the Primary School Dictionary of the English Language from 1874). As a child, I was fascinated with the “pictorial illustrations” on the back. Everything from flags and musical instruments to animals and forms of punishment. My favorite page, however, was always the “Vehicles for Land and Aërial Locomotion.”


It was always fascinating to me how differently everyone chose to travel. They might all be going to the same place, but how they got there was the true story in my mind. Was it a dog-cart, and how big were the dogs?!? Or a Calash, which always resembled Cinderella’s pumpkin carriage in my mind, or maybe even a balloon? My imagination could go wild, and it often did.

The journey-story continues to intrigue me, to this day, and that’s something that we at SparkPost understand. We know that not all of you are coming from the same place, or even trying to solve the same problems. And we certainly know that not all of you are savvy when it comes to JavaScript, and we don’t expect you to be!

We want you to be as successful as possible in all of your email-sending endeavors, with whatever stack you happen to be using. So this is where our client libraries come into play. They’re designed to drop into your existing environment and allow you to access our API in a native-to-you programming language, meaning your lives are presto chango easier (almost) instantly! (You’re welcome 😉)

Since we know how important this service is to you, there’s a lot of process that goes into these libraries. We make sure that they’re tested and ready for you to use on a regular basis. I sat down with a few members of our team to find out about this process and the thought that goes into developing these libraries.

Why Client Libraries?

If you’re like our Developer Advocate Aydrian Howard, you live and breathe JavaScript, which means interacting with our API is fairly straightforward. But let’s say you prefer Python, Java, or some good ol’ PHP.

“It’s really easy for someone using JavaScript, since we pass JSON to our API,” said Aydrian. “But not every programming language has that concept of JSON, so we do that manipulation and pass it over. It makes it more like a function call and less like an API call.”

This means no matter if you’re comfortable using JavaScript or not, you can be up and running with SparkPost quickly and easily.

easy peasy lemon squeezy graphic

But all of this takes work, and we want that to be on us, not on you – easy peasy, remember? Early on in our client library days, we established a set of guidelines for testing, samples, code style, and an explanation of how you, our community, could contribute (wink wink, nudge nudge). These guidelines set us all up for success. For example, making sure that everything is 100% tested before it’s released. They also help make the process easier for you. Our requirement for consistent code style,  based on community best practice, keeps our libraries readable and, thus more maintainable.

If It Ain’t Broke…Right?

When the libraries were first created, each author decided how they would interface with the SparkPost API. Did they want it to be lightweight and simply a wrapper? Or did they want to offer a variety of conveniences for the user, flattening out the parameters? It was the wild west, and we were grateful to any and all who stepped up to the siren call of client libraries.

But then the feedback started coming…

stampede horses

Rich Leland, Director of Growth Engineering, said, “We put our first cut of these libraries out just after having a product launch, and quickly ran into a good problem: we had so much community feedback that we couldn’t reply fast enough!”

We quickly learned that a thin wrapper allowed us to maintain the libraries more easily, as well as keep the libraries relatively lightweight for the community. The heavier libraries were bogging us down. They forced us to completely change each of the client libraries every time we made any changes or additions to the API.

Software Engineer Avi Goldman joined our team just after we noticed this exact problem occurring with our PHP library. He spent time identifying the good bits and then worked on refactoring the rest of it.

“There was already a really good framework for testing,” he said. “We settled on a simple request function and everything revolves around that one central point. Now it’s simply a thin wrapper with some syntactic sugar around the things that are difficult to do, like cc and bcc.”

Basically, there’s now a base resource that can be used to call out to the SparkPost API with a one-to-one mapping that’s consistent between payload parameters in PHP-land, and what is listed in our API documentation. In other words, we’re back to easy peasy lemon squeezy!

Our End Goal: Your Happiness

Ultimately, our goal is to make the lives of our community member’s easier – no matter where they’re coming from. With that goal in mind, we’re always working to improve our API as well as the client libraries. In addition, we’re building various tools and resources to help you along the SparkPost path.

So, what vehicles… err, languages, do you use to get to SparkPost? And how can we, as community advocates, make your journey easier? Come talk to us in Slack, or leave a comment below.

– Mary

p.s. Want to talk to us live? We’ll be talking about client libraries in our next episode of All Things Delivered. Tweet your questions to #SparkPostLive and tune in at 3pm ET on November 16.

PHP in SparkPost

***Update: We’re so glad you’re interested in our SparkPost PHP client library. We pushed a major version change in June 2016, including a complete refactor of the library. It’s now a thin HTTP client layer with some sugar methods on the Transmission class. There is now a base resource that can be used to call any SparkPost API with a one to one mapping of payload parameters to what is listed in our API documentation. Interested in why we did this? Read more about how our client libraries came to be, and how we maintain them. For the most up to date information on our PHP Client Library, check out this article

Using SparkPost in PHP

Just guessing, but if you’re reading this, I’m willing to bet you want to use SparkPost and you probably develop in PHP. In this article, I’m going to go through some basic code so that you can get up and running using PHP and SparkPost.

The SparkPost PHP Client Library

The good news is we have a client library to help you out. It does have a few pre-requisites, but we’ve tried to design the library to be as flexible as possible.

The library requires:

  • PHP 5.5
  • Some sort of request library. This can be cURL or some other library like Guzzle.

Installing & Setup

The SparkPost client library is hosted on and can be installed using composer. If you’ve never used composer, check out their getting started page.

Install using the composer require command:

Cool.  Now that that is taken care of, we should be good to go and can start using SparkPost in code.  Just like using any other composer package, the first step is to require the autoloader and then we can use the SparkPost class.

Now, like I said above in the requirements you have to have some sort of request library or utility available.  This can be cURL or something more like Guzzle. Its really up to you and what is available in your environment. SparkPost currently implements the egeloen/ivory-http-adapter and you can see all of the supported request adapters on their github page. (See sidenote below). You’ll have to implement one of these adapters and pass it into the SparkPost constructor. The second argument is your SparkPost API key.

Here is an example using the cURL adapter:

Here is another example using the Guzzle 6 adapter:

Sidenote on the egeloen/ivory-http-adapter

This library is currently deprecated in favor of php-http/httplug library.  We use Ivory internally to make it simple for you to use whatever HTTP library you want. We do plan to move to the new library in version 2 of the SparkPost PHP Library.

Sending Email

Now that everything is setup, sending your first email is easy. The function you need to know is transmission->send and it takes an associative array with a configuration of the email that you want to send. Some of the more important properties of the config are from, html, text, subject, and recipients, but a full list can be found on the SparkPost PHP Library’s GitHub page.

Here is a simple example:

A more advanced example can include things like substitution data based on each recipient:

Error Handling

If there are any issues performing any operation, the SparkPost library will throw an exception. So in practice, it is a good idea to wrap this send statement in a try-catch block to handle the error properly.

Other Capabilities

Under the hood, the SparkPost client library is just a helper library around our REST APIs.  We are constantly coming out with new APIs with new functionality, and we thought it would be a great idea if you could use the client library with those new APIs as they are released without having to wait for an update.  Thats why we created the setupUnwrapped function. With it, you can use the client library with any of our APIs and use one of four functions to access our REST APIs. Heres how it works in an example getting deliverability metrics:

In the code above, the ‘setupUnwrapped’ function creates a helper for the metrics API and adds it to the ‘$sparky’ instance as a property. This new property has four main functions: get, create, update, and delete.  You can use these functions to access our REST API endpoints which determined by the first parameter.  The second parameter is either an array that maps to a query string like the example above, or an array that gets json encoded as the post body depending on which method you choose.  ‘$results’ will contain the API response.  The good news is that this method works even if we choose to add support for the same endpoint in the future. So you don’t have to worry about breaking code when you update.  Since this method of “build your own helper” relies on directly utilizing the our REST APIs, you should familiarize yourself with our API documentation when using it.

For more information please checkout the SparkPost PHP Library on GitHub, our developer hub, or come talk to our team in our community Slack.


Dev Survival Guide Blog Footer

php client library

We are proud to announce a new release of the php-sparkpost library at version 1.0.0!  After receiving feedback from the community, we have dramatically overhauled the library to be easier to use and more flexible.  

One of the biggest changes that we’ve made in this release is the use of HTTP adapters.  Since the library is built on top of the SparkPost REST API, one of the biggest challenges that we faced in previous versions was the ability to use our library with other libraries that also made HTTP requests.  We had originally chosen to ship our client library with Guzzle, a popular HTTP request library, but this unfortunately came with the side effect of version mismatches and dependency hell for our users.

Enter HTTP adapters.  HTTP adapters allow us to present the same interface to the user and allows us to use the same interface within the library for any HTTP request library or tool that the user decides to implement.  The user simply has to instantiate an adapter for the library that they are using and pass it into the SparkPost constructor when they instantiate it.  We use the Ivory\HttpAdapter library which is PSR-7 compliant.  PSR-7 is a specification for HTTP message interfaces in PHP.

For example if you use a library like Guzzle:

Or if you’re using something like CURL:

The second major change is that we switched from a static interface to an instance based one. This doesn’t change much for the end user of the library besides only needing to include one package instead of two and swapping a few ‘::’ operators for ‘->’ operators, but between this and the adapter changes mentioned above, this version isn’t a simple drop in replacement for previous versions (which is why we’re releasing as v1.0). However, as the library’s toolset grows, we hope these changes offer developers the ability to access all of its functionality from a single reference and with a shared configuration across all of those tools.

Here is a simple example of sending an email with SparkPost after setting it up above: 

We also added a new feature to be able to use the library to take advantage of other API endpoints that aren’t currently supported.  We do this with a new ‘setupUnwrapped’ method passing in the endpoint name. Doing so exposes basic create, update, get, and delete methods which will support bodies and parameters outlined in our API documentation.  This is a little hard to explain but it may be easier to see with an example:

The composer packagist repository for the library resides here

It can be installed using composer:

Please feel free to try it out in your projects. If you have feedback or would like to make a contribution please feel free to submit an issue or a pull request on the GitHub repository.