“Subscribers” have become “Contacts”

Today we rolled out an important change to our platform. In an effort to make email marketing more understandable and closer to our clients, we decided to change the way we address your contacts. They will no longer be called “Subscribers” in the system, but “Contacts”.

A couple of things worth knowing:

  • Subscribers are from now known as Contacts
  • Opted-in subscribers will now be “confirmed contacts”
  • If a contact does not have a name we will refer to them as “Recipient” for any personalized content
  • The API has changed to reflect this update. Old API calls will continue to work as they did before.
  • Your existing Web Hooks will still work as expected.

A new subscriber/contact list page

Today we released a new version of our subscriber list page (which we will be referring to as “Contacts” in the near future)

In our on-going mission to help you know your subscribers at a deeper personal level, we are now including personal details about them right in the list view.  This includes:

  • A photo of your contact is shown when available
  • The location of the contact is shown when available
  • Social profiles (Twitter, Facebook, LinkedIn) are shown when available.  (currently requires you to subscribe to ERJA)
  • You are able to email a single contact directly form the contact list page
  • Custom fields (that you choose to show on the list page) are now shown under the contact.  This allows you to show many more fields in a clean & easy to read format.

The Trouble with Imports (APC & PHP setlocale bizarreness)

As some of you may have noticed, we had a few problems with our import system last week. After several hours of investigation and a fix gratefully being applied, we wanted to share some of the details of what happened.

The Short Version

As of late last week, we noticed some problems when people were visiting the Subscriber Import page. Many times, things would work fine; sometimes, you might be shown a server error. That’s pretty confusing (and frustrating!) for anyone; the worst part was, though we could reproduce it, we couldn’t make any sense of it.

After a lot of investigation, we were able to track down the problem to some new code we added around that time. Our intention was to set the locale, useful for those with languages that may format dates a bit differently than English, but it turns out our cache system (which helps us serve pages as fast as we do) had some problems working with different locales.

You might be thinking that doesn’t make any sense. We think you’re right, and we were pretty confused; this was not the most straightforward debugging session, to say the least. But our testing confirms that code was the culprit.

If you’re worried about the locale not being set, don’t fret; we have some plans to reintroduce that feature, but in another form. From here on, your visits to the import page should be error-free.

The Long and Technical Version

As a programmer, I like bugs that make sense: the page isn’t loading, and there’s a typo? That would do it. Oh, we forgot to save this color change to the database; that’s why it’s not reflected when I refresh the page.

I don’t like bugs that make no sense, so the bug here was pretty frustrating not only for me but everyone in the office. It began happening in a third-party library for connecting to Google Contacts: one of the interfaces there (apiIO) was not defined. What an odd thing, particularly for some code we’d been using for a while; the bug nevertheless corresponded with a new feature we released, and we were pretty wary that something with that feature wasn’t interacting well with the rest of our software.

Not soon after we began looking, we had disabled APC, which is the cache system we use for PHP, and the error magically disappeared. That’s stranger, and told us right away that whatever we were looking for wasn’t going to make a lot of sense. (We were right about that in the end.) It also told us that we needed to be a bit less conventional in our thought process.

The interface in question is, of course, present in one of the code files of Google’s library. We thought perhaps the way those files are included doesn’t work well with APC, so we stopped what Google was doing (setting the system’s include path) and changed the library to include files using an absolute path. It seemed like it was working! — but then we saw server errors again. Back to the drawing board.

The apiIO interface is really the only one in the library, and we don’t tend to use that particular feature of PHP ourselves. What’s an interface but a class with empty methods, right? So we changed apiIO to actually be a class. It seemed like it was working! — but no.

Sigh. Well, APC is turned off for now, and in the meantime another error popped up in which some methods in a class our sending engine uses seemed not to exist, so we turned our attention to that (since sending is important). (It should be pointed out that this problem was only affecting one of our users — everyone else was able to send just fine.) Turns out the class has all the methods it should; if you run the PHP function to grab all of the class methods, they’re all there. But it turns out a few of them are missing from the object.

Let’s make it weirder. The methods that were missing all had a capital letter ‘I’. They should be there, but they weren’t, and by this time we were thinking this was more like magic than programming. We knew by the time the error happens that the methods are gone; we also knew, through testing, that when we start to send with this example, the methods are there. Sometime in the middle, they go away — which is weirder still.

So we did divide and conquer; pick some code that runs half-way through the error case and the beginning. Are the methods there or not? On and on we went, brute-force, until we tracked it down to — PHP’s setlocale function. Huh?

This particular user had been using our Turkish language support. Setting the locale for that turns out to have a longstanding bug in PHP, one in which our version was still susceptible. It seems that setting the locale has a somewhat illogical but nevertheless destructive impact on class methods (in particular, with the capital letter ‘I’). When we stopped setting the locale, sending was fixed.

And then we thought, hey — that error with Google’s library when APC was turned on? Didn’t that interface have a capital letter ‘I’ in it? It did! But the people getting the error weren’t using Turkish; they were, in many cases, using only English. Still, we had a theory, and it sort of made twisted sense. So we turned off setting the locale for everyone, and turned on APC, and…

It worked. The import page; everything worked. It shouldn’t have mattered, and it still doesn’t make any sense, but setting the locale made methods, classes and interfaces disappear, in particular those with a capital letter ‘I’. Thus ended one of the most bizarre debugging sessions our developers have ever had.

Connect with External Services for Automatic Importing

Our external imports (to services like Salesforce, Wufoo, and Capsule) has always been a manual, one-time import. This is fine is you just start using our service and would like to bring in everyone from another service. The problem is that every time you update someone in the external service, that change would not come across to ActiveCampaign until you re-imported. This became a redundant task which reduced the effectiveness of the feature.

So we spent some time updating the import section to allow for automated imports from external services. When you connect to your external service you’ll have the option to let us check for new updates on a recurring basis (a few times an hour or week), or to use the old approach (non-recurring, one-time import):

You can still supply import filters to narrow down the data, and we’ll automatically check if the subscriber already exists (if so, their details are updated).

We’ve also removed the mapping step (where you mapped fields from the external source into ActiveCampaign fields) in order to simplify the entire process. Instead we hand-pick as many relevant fields coming from the external source and automatically create custom fields (and map the data) in ActiveCampaign for you:

Notice in the screenshot above that the new custom fields are labeled with the external source name to start the personalization tag (IE: batchbook-about). This makes it easy to identify the field related to a specific external import source. When the import process runs again (on a recurring basis) it will continue to update those custom fields with data. This speeds up the entire process and let’s you focus on crafting relevant email campaigns for your subscribers.

Initially we’re allowing this new automatic import to happen for four external sources, and plan to add the rest of them very soon:

  1. Nimble
  2. Contactually
  3. Capsule
  4. Batchbook

You will know if a particular source is set up for automatic import if it shows “Auto-Import Capable” beneath it:

For any source that does not have automatic import enabled, you can still perform an import using the old approach (manual, one-time, and ability to map fields on your own).

You can also connect multiple external accounts (using different users or API keys) per source. For example, if you have multiple Contactually accounts (or users with different API access), they can all be added through a single ActiveCampaign account and have an automatic import set up for each.

We are excited to release this improved method of importing subscribers, and we’ll be on the watch for any initial issues, so please let us know if you have any questions, problems, or feedback!

Note: We are slowly rolling this out to all accounts so it might not be available immediately.

Updates to the subscriber view page

Subscriber notes

Ever want to jot something down about a subscriber?  Now you can.  The new subscriber notes tab allows you to add and view any notes pertaining to a specific subscriber.  You can even utilize the API & webhooks to manage this data.

Making social data easier to find

When viewing a subscriber we will now show any available social networks that they are part of as icons underneath their email address.

Email a single subscriber directly or download their vCard

For each subscriber you will now see a new email icon for contacting them directly and a vCard icon to download their vCard file.  You can then import into any application that accepts vCards.

Improved GEO location data

We have been tracking the location and travel locations of your subscribers.  Now we are determing their timezone and showing you their current time along with the ability to discover their travel trends with a larger map.  (expect to see timezone related features popping up throughout the software in the future)

Save Time and Clicks with Smart Search

image

We’ve added a new search utility to the header portion of the software, but this is no ordinary search. Instead of searching actual data, we’ve designed it to search sections of the software that you’d normally have to find by navigating our user interface.

What’s the purpose, you might wonder? To save you time when accessing common sections, and helping reveal sections you may not have known existed.

For example, try typing “sub” into the search box, and notice that relevant page results show up:

image

You can search for any page within the software and it will let you easily navigate to it without jumping in between multiple pages just to get to your destination.

The search is designed to use natural language to find relevant pages. It will show results almost instantly (after two characters are entered) with a lot of smart features and friendly keyboard navigation options:

  • Tapping the “S” key will expand the search box and focus the cursor (so you can begin typing immediately).
  • Tapping “Esc” will collapse the search box (after expanding it).
  • The up and down arrow keys will cycle between result items.
  • Hitting “Enter” on any item will immediately redirect you to that page.
  • Since the first item is always selected by default, hitting “Enter” right away will take you to the top item.
  • If no results are returned, hitting “Enter” will redirect to the Subscribers page with a search conducted for the phrase you entered (you can also click “Search Subscribers” at any time to conduct a subscriber search).
  • You can also opt to search campaign data by clicking “Search Campaigns” (which will direct you to that page with your search included).
  • Multiple language support is included.
  • Permissions and branding settings are taken into account.

Here are some more examples of how convenient this can be, and how it might make your workflow a lot easier.

Start typing “invoice” to find the “Billing History” section:

image

Start typing “upgrade” to find the “Billing & Upgrade” section:

image

Looking for Facebook-related sections?

image

Integrations are also easier to find (search by the name of the service):

image

We are constantly improving our index with common search terms to help you locate almost any page or section within the software. We also have future plans to give more “weight” to commonly accessed pages (based on your own history) so it could become tailored to your own habits.

Give it a whirl and let us know what you think!

Webhooks Now Available

We are excited to announce support for webhooks which allow you to capture real-time data/requests coming from ActiveCampaign to use in other applications.

Overview

Webhooks differ from our standard API in that they are event-driven, meaning they automatically run behind the scenes whenever a particular event happens in the system (such as a campaign sending, or a subscriber’s details being updated), whereas our standard API requires that you initiate the requests to receive data.

Webhooks allow a much more fluid exchange of data between applications because they reduce the need for applications to poll for new data on a routine basis, which can be a waste of system resources. With webhooks, your applications can listen for new requests to come across, and only perform actions when a request arrives.

Here is an overview of all available webhook types for ActiveCampaign:

  • A new subscription occurs
  • An unsubscription occurs
  • A subscriber updates their details
  • A campaign starts sending
  • A campaign is opened
  • A subscriber clicks a link from a campaign
  • A subscriber forwards a campaign
  • A subscriber shares a campaign to Facebook or Twitter
  • A new bounce occurs after sending a campaign

When any of the above events happen, you can post the corresponding data to any URL. You can set up multiple URL’s (per event) and even specify how the event was initialized (by a subscriber, by an admin user, by the API, or by a system process).

Screenshot of Webhooks page in ActiveCampaign

Please see our Webhooks information page for details on each event/type and what data fields are included.

Real world use-cases

Here are some real-world examples of what you can do with ActiveCampaign webhooks:

  1. Keep subscriber records in sync with an external database or application.
  2. Capture campaign reactions (opens, link clicks, forwards, shares) to push real-time stats to another system or application.
  3. Maintain an external unsubscribe or bounce list.
  4. Know when campaigns start sending so you can track usage.

Managing webhooks

You can add, edit, and delete webhooks by going to the “Integration” tab, then clicking the “Webhooks” link on the right side:

Screenshot of where to add webhooks in ActiveCampaign

You can also manage webhooks using our API (example).

Capturing webhooks in your code

Below is an example of data being pushed to a URL after a subscriber is added, and how you can read the data using PHP:

<?php

// this is a webhook page to capture new subscriptions

if ($_SERVER["REQUEST_METHOD"] == "POST") {

  $webhook_data = $_POST;
  
  // basic validation check
  if (!isset($webhook_data["subscriber"]["id"])) exit();

  $subscriber_id = $webhook_data["subscriber"]["id"];
  $subscriber_email = $webhook_data["subscriber"]["email"];
  // ... etc

  /* 
  $webhook_data looks like:

  Array
  (
    [type] => subscribe
    [date_time] => 2013-01-02 09:28:42
    [initiated_from] => admin
    [initiated_by] => admin
    [list] => 12
    [subscriber] => Array
      (
        [id] => 12
        [email] => test@test.com
        [first_name] => Test
        [last_name] => Test
        [ip] => 127.0.0.1
        [fields] => Array
          (
            [7] => test value
            [16] => 2013-01-03
            [15] => value 1
          )
      )
  )
  */
} 

?>

Other important information

Here is some other important information regarding ActiveCampaign webhooks:

  1. Webhooks are List-based, meaning they will only fire when an event occurs for the list associated with the webhook.
  2. We hit your webhook URL(s) within a minute of the event occurring.
  3. Only data that is available during the request will be included. For example, unsubscriptions may not include the reason right away because that happens after the unsubscription does.

Let us know of any questions, and how you plan to use ActiveCampaign webhooks!

Viewing your recent campaigns from the startup page

Yesterday a minor update went live to the startup page where we normally show drafts and templates.

If you have sent campaigns recently we now show the 3 most recent campaigns instead of 3 templates.

This allows quick access to the campaign reports along with your campaign drafts which is still listed on the startup page.

 

 

 

 

 

 

Exploring Our API

At ActiveCampaign we want our users to interact with the software in any way they wish. Although we work hard to make our standard interface as usable and friendly as possible, sometimes there are things that are missing or not as easy to configure. With software development it is difficult to please every user.

Our API allows developers to craft their own interface, processes, and experience that utilize the power of ActiveCampaign within their own applications and websites. To make this easier, we are creating an “API Explorer” that users can access within the software and fully interact with the API using real data and examples.

Check it out under your settings, API section:

Screenshot of API Explorer

You can simulate API requests through this simple interface which also shows you all relevent information you’ll need to make API requests through your own applications and websites.

The basic idea is to choose a method and supply the necessary parameters. Then hit the “View API Response” button to see the actual response, or to test it (which only shows the parameters you would include with the request, in case you don’t want to update live data).

Screenshot of API Explorer

Below is some more information and screenshots for each section.

Request URL: The URL you request/submit to when getting or posting data.

Screenshot of API Explorer

You can use this URL in any programming language where you can submit HTTP requests (to send or receive data from other servers).

Method Parameters: All available parameters that can be included with the request.

Screenshot of API Explorer

Parameters are the specific settings or values needed to achieve the request. Think of them as the same fields you fill out in our standard admin interface when creating a campaign. For example: campaign name, type, lists, message used, etc.

Response: The actual response that comes back from the server after submitting a request.

Screenshot of API Explorer

The response always contains a result_code which tells you whether the request succeeded or failed. It also includes extra information related to the request, such as the new unique ID created (for example, when creating a subscriber or campaign), which you can use in subsequent requests.

Also, above we are receiving JSON-formatted data back. You can also receive XML or serialized data.

Request and Parse: Example using our PHP library on how to make the request and parse the response.

Screenshot of API Explorer

We provide the exact code needed to make the request and read the response. You can copy all (or portions) of this into your own application for getting set up very quickly.

Our goal with the API is to get developers up and running quickly, while providing extensive documentation and examples so issues or problems can be discovered and fixed easily.

Stay tuned for future developments and changes to our API Explorer as we continue to improve the interface and add new API methods and parameters. Let us know if you have any questions or problems.

Updates to Google Contacts and Spreadsheets Importing

Using our subscriber import tool, you can easily connect to your Google account to retrieve your contacts or spreadsheets. Until now, there was a couple of lingering problems with this:

1. There was no way to filter by Contact “Group” (groups you set up in Google Contacts), and that seems to be the most obvious way to organize your contacts for importing into ActiveCampaign.
2. Loading spreadsheets from your Google Docs account (through ActiveCampaign’s interface) could take a while (depending on how many you had).

We’ve updated our importer to allow for filtering on Google Contacts groups:

Screenshot of ActiveCampaign import filters

(You can still filter using a free-form text search, which looks for matches among all data fields.)

For importing Google spreadsheets, retrieving all of your spreadsheets now loads much faster. You can still filter on spreadsheet and worksheet:

Screenshot of ActiveCampaign import filters

Screenshot of ActiveCampaign import filters

As always, make sure your spreadsheets are clean and readable for the best possible result.

We also have an improved authorization process for both Google products:

Screenshot of Google authorization/OAuth process for Contacts

Screenshot of Google authorization/OAuth process for Spreadsheets

Please let us know if you have any questions or problems!