Documentation

Javascript Snippet

To get started include the following snippet in the footer of your website. (Note that the signup_date should be either an ISO timestamp, or the number of seconds since epoch.)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<script type="text/javascript">
var _ufq = _ufq || [];

_ufq.push(["init", {clientId: "4v2erxr9c5vzqsy35z9gnk6az", email: "<%= current_user.email %>"}]);
_ufq.push(["track", {signup_date: "<%= current_user.created_at %>"}]);

(function() {
    var ufs = document.createElement("script");
    ufs.type="text/javascript"
    ufs.src=document.location.protocol+"//d2y71mjhnajxcg.cloudfront.net/js/userfox-stable.js"
    ufs.async=true;
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(ufs, s);
})()
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<script type="text/javascript">
var _ufq = _ufq || [];

_ufq.push(["init", {clientId: "4v2erxr9c5vzqsy35z9gnk6az", email: "{{ user.email }}"}]);
_ufq.push(["track", {signup_date: "{{ user.created_at }}"}]);

(function() {
    var ufs = document.createElement("script");
    ufs.type="text/javascript"
    ufs.src=document.location.protocol+"//d2y71mjhnajxcg.cloudfront.net/js/userfox-stable.js"
    ufs.async=true;
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(ufs, s);
})()
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<script type="text/javascript">
var _ufq = _ufq || [];

_ufq.push(["init", {clientId: "4v2erxr9c5vzqsy35z9gnk6az", email: "#email#"}]);
_ufq.push(["track", {signup_date: "#created_at#"}]);

(function() {
    var ufs = document.createElement("script");
    ufs.type="text/javascript"
    ufs.src=document.location.protocol+"//d2y71mjhnajxcg.cloudfront.net/js/userfox-stable.js"
    ufs.async=true;
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(ufs, s);
})()
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<script type="text/javascript">
var _ufq = _ufq || [];

_ufq.push(["init", {clientId: "4v2erxr9c5vzqsy35z9gnk6az", email: "<%= user.getEmail() %>"}]);
_ufq.push(["track", {signup_date: "<%= user.createdAt() %>"}]);

(function() {
    var ufs = document.createElement("script");
    ufs.type="text/javascript"
    ufs.src=document.location.protocol+"//d2y71mjhnajxcg.cloudfront.net/js/userfox-stable.js"
    ufs.async=true;
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(ufs, s);
})()
</script>

Signup Date Format

The signup_date should be sent to us either as a string formatted either as an ISO timestamp, or the seconds since epoch.

Examples

For example these will yield the correct signup_date format:

now.toISOString()
Time.now

Here is the explicit format of the ISO timestamp to serve as an example:

signup_date: "2012-10-24 19:28:00 +0000"

Custom data

You can additionally push userfox custom data about your users. This data can be any data you know about the user: pricing plan, date of trial expiry, number of friends, first name, and so on. userfox understands that a date is in date format, and will allow you to build rules around any custom data you send.

In this example, we are pushing the users name as well as the special custom data type signup_date to userfox: (line 5)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<script type="text/javascript">
var _ufq = _ufq || [];

_ufq.push(["init", {clientId: "4v2erxr9c5vzqsy35z9gnk6az", email: "<%= current_user.email %>"}]);
_ufq.push(["track", {signup_date: "<%= current_user.created_at %>", name: "<%= current_user.name %>"}]);

(function() {
    var ufs = document.createElement("script");
    ufs.type="text/javascript"
    ufs.src=document.location.protocol+"//d2y71mjhnajxcg.cloudfront.net/js/userfox-stable.js"
    ufs.async=true;
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(ufs, s);
})()
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<script type="text/javascript">
var _ufq = _ufq || [];

_ufq.push(["init", {clientId: "4v2erxr9c5vzqsy35z9gnk6az", email: "{{ user.email }}"}]);
_ufq.push(["track", {signup_date: "{{ user.created_at }}", name: "{{ user.name }}"}]);

(function() {
    var ufs = document.createElement("script");
    ufs.type="text/javascript"
    ufs.src=document.location.protocol+"//d2y71mjhnajxcg.cloudfront.net/js/userfox-stable.js"
    ufs.async=true;
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(ufs, s);
})()
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<script type="text/javascript">
var _ufq = _ufq || [];

_ufq.push(["init", {clientId: "4v2erxr9c5vzqsy35z9gnk6az", email: "#email#"}]);
_ufq.push(["track", {signup_date: "#created_at#", name: "#name#"}]);

(function() {
    var ufs = document.createElement("script");
    ufs.type="text/javascript"
    ufs.src=document.location.protocol+"//d2y71mjhnajxcg.cloudfront.net/js/userfox-stable.js"
    ufs.async=true;
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(ufs, s);
})()
</script>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<script type="text/javascript">
var _ufq = _ufq || [];

_ufq.push(["init", {clientId: "4v2erxr9c5vzqsy35z9gnk6az", email: "<%= user.getEmail() %>"}]);
_ufq.push(["track", {signup_date: "<%= user.createdAt() %>", name: "<%= user.getName() %>"}]);

(function() {
    var ufs = document.createElement("script");
    ufs.type="text/javascript"
    ufs.src=document.location.protocol+"//d2y71mjhnajxcg.cloudfront.net/js/userfox-stable.js"
    ufs.async=true;
    var s = document.getElementsByTagName("script")[0];
    s.parentNode.insertBefore(ufs, s);
})()
</script>

Custom Data Dates

You can additionally send us dates as custom data, such as when a users trial will expire. This should be formatted as an ISO timestamp, and sent as a string.

Email Templates

Email templating is handled by liquid templating format. Our editor handles all basic editing, the most common custom use case is inserting data that you have previously pushed (through the javascript snippet) to userfox, such as the users name:

Using data in templates

Any custom data can be used in a template, such as:

Hi {{name}},

Data outside of Custom Data

There are two default pieces of data you can insert in all emails:

Your product name (as defined in Settings):

{{product_name}}

The users email address:

{{email}}

Liquid Templating

You can add basic logic to your templates. You might add:

{% if payments < 1 %}
    You have yet to buy an item! Use this promo code 'buy104' to get a 5% discount
{% endif %}

This is a great - and dead simple - way to gently nudge the user to do something. You can naturally do far more elaborate logic with the data you push to userfox.

Only have some users that enter their name in your web application?

{% if name %}
    Hi {{ name }}
{% endif %}

Rest API

If the JavaScript doesn’t work for you for any reason we also support a Rest API. We support event tracking, transactional email, unsubscribes, and change of email address right now from our API. When sending custom user data, you need only send a delta for data that has changed. You must send the deltas formatted as a JSON. The endpoint for the API is https://api.userfox.com/v1

Creating users

Users are created if you simply use our Tracking restful call (next section below) and include a signup_date in the delta.

Tracking

Track activity on website or application.

require 'restclient'

RestClient.post
  'https://4v2erxr9c5vzqsy35z9gnk6az:eto0trnoddk1o0fgf77b99zdg@api.userfox.com/v1/track.json',
  {:addr => "cesar@userfox.com", :url => "http://userfox.com/docs/index.html",
    :delta => "{\"name\": \"Cesar Alaniz\", \"signup_date\": \"2013-05-17 19:54:11 UTC\", \"sent\": 10}"}
import requests

requests.post(
    "https://api.userfox.com/v1/track.json",
    auth=("4v2erxr9c5vzqsy35z9gnk6az", "eto0trnoddk1o0fgf77b99zdg"),
    data={"addr": "cesar@userfox.com",
          "url": "http://userfox.com/docs/index.html",
    "delta": "{\"name\": \"Cesar Alaniz\", \"signup_date\": \"2013-05-17 19:54:11 UTC\", \"sent\": 10}"}
<?
  $ch = curl_init();

  curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
  curl_setopt($ch, CURLOPT_USERPWD, '4v2erxr9c5vzqsy35z9gnk6az:eto0trnoddk1o0fgf77b99zdg');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
  curl_setopt($ch, CURLOPT_URL, 'https://api.userfox.com/v1/track.json');
  curl_setopt($ch, CURLOPT_POSTFIELDS, array('addr' => 'cesar@userfox.com',
                                         'url' => 'http://userfox.com/docs/index.html',
                                         'delta' => '{\"name\": \"Cesar Alaniz\", \"signup_date\": \"2013-05-17 19:54:11 UTC\", \"sent\": 10}"}'))

  $result = curl_exec($ch);
  curl_close($ch);

?>
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

Client client = Client.create();
client.addFilter(new HTTPBasicAuthFilter("4v2erxr9c5vzqsy35z9gnk6az",
                   "keto0trnoddk1o0fgf77b99zdg"));
WebResource webResource =
        client.resource("https://api.userfox.com/v1/track.json");
MultivaluedMapImpl formData = new MultivaluedMapImpl();
formData.add("addr", "cesar@userfox.com");
formData.add("url", "http://userfox.com/docs/index.html");
formData.add("delta", "{\"name\": \"Cesar Alaniz\", \"signup_date\": \"2013-05-17 19:54:11 UTC\", \"sent\": 10}"}");
POST /track.json
param addr:the address of the user tracking
param url:url or uri of event
param delta:JSON changed user info data as a string.
statuscode 200:success
statuscode 401:unauthorized

HTTP request:

POST /track.json HTTP/1.1
Host: userfox.com
Authentication: Basic NHYyZXJ4cjljNXZ6cXN5MzV6OWduazZhejpldG8wdHJub2RkazFvMGZnZjc3Yjk5emRn
Accept: application/json, text/javascript

url=http%3A%2F%2Fuserfox.com%2Fdocs%2Findex.html&addr=cesar%40userfox.com&delta=%%7B%22name%22:%20%22Cesar%20Alaniz%22,%20%22count%22:%2010%7D

HTTP response:

HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript

{"status":"Success","detail":"Ok","callbackId":"1"}

Unsubscribes

Unsubscribe a email address from all emails. (including transactional)

require 'restclient'

RestClient.post
  'https://4v2erxr9c5vzqsy35z9gnk6az:eto0trnoddk1o0fgf77b99zdg@api.userfox.com/v1/unsubscribes.json',
    {:addr => "cesar@userfox.com"}
import requests

requests.post(
    "https://api.userfox.com/v1/unsubscribes.json",
    auth=("4v2erxr9c5vzqsy35z9gnk6az", "eto0trnoddk1o0fgf77b99zdg"),
    data={"addr": "cesar@userfox.com"})
<?
  $ch = curl_init();

  curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
  curl_setopt($ch, CURLOPT_USERPWD, '4v2erxr9c5vzqsy35z9gnk6az:eto0trnoddk1o0fgf77b99zdg');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
  curl_setopt($ch, CURLOPT_URL, 'https://api.userfox.com/v1/unsubscribes.json');
  curl_setopt($ch, CURLOPT_POSTFIELDS, array('addr' => 'cesar@userfox.com'))

  $result = curl_exec($ch);
  curl_close($ch);

?>
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

Client client = Client.create();
client.addFilter(new HTTPBasicAuthFilter("4v2erxr9c5vzqsy35z9gnk6az",
                   "keto0trnoddk1o0fgf77b99zdg"));
WebResource webResource =
        client.resource("https://api.userfox.com/v1/unsubscribes.json");
MultivaluedMapImpl formData = new MultivaluedMapImpl();
formData.add("addr", "cesar@userfox.com");
POST /unsubscribes.json
param addr:the address of the user unsubscribing

HTTP request:

POST /unsubscribes.json HTTP/1.1
Host: userfox.com
Authentication: Basic NHYyZXJ4cjljNXZ6cXN5MzV6OWduazZhejpldG8wdHJub2RkazFvMGZnZjc3Yjk5emRn
Accept: application/json, text/javascript

addr=cesar%40userfox.com
(optional) campaign= welcome, inactivity, newsletter or transactional

HTTP response:

HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript

{"status":"Success","detail":"Ok","callbackId":"1"}

Re-subscribes

Simply send above http request, but instead of as a POST send a delete, with the addr of the unsubscribed user.

Change Email Addrs

Sometimes you may wish to change an existing users email address, for example if they change it in your application settings.

require 'restclient'

RestClient.post
  'https://4v2erxr9c5vzqsy35z9gnk6az:eto0trnoddk1o0fgf77b99zdg@api.userfox.com/v1/change.json',
    {:from => "cesar@userfox.com", :to => "cesar@userfox.org"}
import requests

requests.post(
    "https://api.userfox.com/v1/change.json",
    auth=("4v2erxr9c5vzqsy35z9gnk6az", "eto0trnoddk1o0fgf77b99zdg"),
    data={"from": "cesar@userfox.com",
          "to": "cesar@userfox.org"})
<?
  $ch = curl_init();

  curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
  curl_setopt($ch, CURLOPT_USERPWD, '4v2erxr9c5vzqsy35z9gnk6az:eto0trnoddk1o0fgf77b99zdg');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
  curl_setopt($ch, CURLOPT_URL, 'https://api.userfox.com/v1/change.json');
  curl_setopt($ch, CURLOPT_POSTFIELDS, array('from' => 'cesar@userfox.com',
                                         'to' => 'cesar@userfox.org'))

  $result = curl_exec($ch);
  curl_close($ch);

?>
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

Client client = Client.create();
client.addFilter(new HTTPBasicAuthFilter("4v2erxr9c5vzqsy35z9gnk6az",
                   "keto0trnoddk1o0fgf77b99zdg"));
WebResource webResource =
        client.resource("https://api.userfox.com/v1/change.json");
MultivaluedMapImpl formData = new MultivaluedMapImpl();
formData.add("from", "cesar@userfox.com");
formData.add("to", "cesar@userfox.org");
POST /change.json
param to:the address to change
param from:the address to change to

HTTP request:

POST /change.json HTTP/1.1
Host: userfox.com
Authentication: Basic NHYyZXJ4cjljNXZ6cXN5MzV6OWduazZhejpldG8wdHJub2RkazFvMGZnZjc3Yjk5emRn
Accept: application/json, text/javascript

from=cesar%40userfox.com&to=cesar%40userfox.org

HTTP response:

HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript

{"status":"Success","detail":"Ok","callbackId":"1"}

Transactional Emails

It is possible to send transactional emails via userfox. These emails are simply sent from your code base, example use cases are things like Password Recovery emails.

require 'restclient'

RestClient.post
  'https://4v2erxr9c5vzqsy35z9gnk6az:eto0trnoddk1o0fgf77b99zdg@api.userfox.com/v1/send.json',
  {:addr => "cesar@userfox.com", :name => "Password Recovery",
    :delta => "{\"tmp-password\": \"nORqw47dcaPlbL\"}"}
import requests

requests.post(
    "https://api.userfox.com/v1/send.json",
    auth=("4v2erxr9c5vzqsy35z9gnk6az", "eto0trnoddk1o0fgf77b99zdg"),
    data={"addr": "cesar@userfox.com",
          "name": "Password Recovery",
          "delta": "{\"tmp-password\": \"nORqw47dcaPlbL\"}"})
<?
  $ch = curl_init();

  curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
  curl_setopt($ch, CURLOPT_USERPWD, '4v2erxr9c5vzqsy35z9gnk6az:eto0trnoddk1o0fgf77b99zdg');
  curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

  curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
  curl_setopt($ch, CURLOPT_URL, 'https://api.userfox.com/v1/send.json');
  curl_setopt($ch, CURLOPT_POSTFIELDS, array('addr' => 'cesar@userfox.com',
                                         'name' => 'Password Recovery',
                                         'delta' => '{"tmp-password": "nORqw47dcaPlbL"}'))

  $result = curl_exec($ch);
  curl_close($ch);

?>
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;

Client client = Client.create();
client.addFilter(new HTTPBasicAuthFilter("4v2erxr9c5vzqsy35z9gnk6az",
                   "keto0trnoddk1o0fgf77b99zdg"));
WebResource webResource =
        client.resource("https://api.userfox.com/v1/send.json");
MultivaluedMapImpl formData = new MultivaluedMapImpl();
formData.add("addr", "cesar@userfox.com");
formData.add("name", "Password Recovery");
formData.add("delta", "{\"tmp-password\": \"nORqw47dcaPlbL\"}");
POST /send.json
param name:name of the transactional email trigger.
param addr:the address of the user. May also pass a list of comma separated addresses.
param delta:JSON changed user info data as a string.
statuscode 200:success
statuscode 401:unauthorized

HTTP request:

POST /send.json HTTP/1.1
Host: userfox.com
Authentication: Basic NHYyZXJ4cjljNXZ6cXN5MzV6OWduazZhejpldG8wdHJub2RkazFvMGZnZjc3Yjk5emRn
Accept: application/json, text/javascript

addr=cesar%40userfox.com&name=Password%20Recovery&delta=%7B%22tmp-password%22:%20%22nORqw47dcaPlbL%22%7D

HTTP response:

HTTP/1.1 200 OK
Vary: Accept
Content-Type: text/javascript

{"status":"Success","detail":"Ok","callbackId":"1"}

Secure Mode

For extra security, you can secure the JS client by passing a signature to the init method options. To compute the signature, you concatenate your clientId and the user email address together and run HMAC encryption with a secret key we provide you. You must enable secure mode from your account settings.

require 'openssl'

signature = OpenSSL::HMAC.hexdigest(
  OpenSSL::Digest::Digest.new("sha256"),
  "eto0trnoddk1o0fgf77b99zdg",
  "%s%s" % ["4v2erxr9c5vzqsy35z9gnk6az", current_user.email])
from hashlib import sha256
import hmac

digest = hmac.new("eto0trnoddk1o0fgf77b99zdg",
  "%s%s" % ("4v2erxr9c5vzqsy35z9gnk6az", user.email), sha256)
signature = digest.hexdigest()
<?php
  $signature = hash_hmac("sha256", "4v2erxr9c5vzqsy35z9gnk6az" + email, "eto0trnoddk1o0fgf77b99zdg");
?>
SecretKeySpec keySpec = new SecretKeySpec(
  "eto0trnoddk1o0fgf77b99zdg".getBytes(),
  "HmacSHA1");

Mac mac = Mac.getInstance("HmacSHA1");
mac.init(keySpec);
byte[] result = mac.doFinal(("4v2erxr9c5vzqsy35z9gnk6az" + user.getEmail()).getBytes());

BASE64Encoder encoder = new BASE64Encoder();
String signature = encoder.encode(result);

Then pass the result of this computation to the javascript init method

_ufq.push(["init",
  {clientId: "4v2erxr9c5vzqsy35z9gnk6az", email: "<%= current_user.email %>",
    signature: "<%= signature %>"}]);
_ufq.push(["init",
  {clientId: "4v2erxr9c5vzqsy35z9gnk6az", email: "{{ user.email }}",
    signature: "{{ signature }}"]);
_ufq.push(["init",
  {clientId: "4v2erxr9c5vzqsy35z9gnk6az", email: "<? echo email ?>",
    signature: "<? echo signature ?>"}]);
_ufq.push(["init",
  {clientId: "4v2erxr9c5vzqsy35z9gnk6az", email: "<%= user.getEmail() %>",
    signature: "<%= signature %>"}]);

Support

Please email us if you have any questions!

← back to userfox