Woopra Documentation

Suggest Edits

Intro: Tracking SDK's

 

The tracking SDK's are small packages with convenience functions written in different languages. Essentially what they do is wrap the HTTP Tracking API, which is the core to all tracking in Woopra.

The most detailed general tutorial for using tracking sdks can be found in the Browser Javascript API. Though it has some functionalities, such as the ping, that are not supported in the serverside SDKs.

The SDK's listed on the left in this section are all links to the github repositories. The most up-to-date docs are in the README.md file in the base directory of those repositories. You can get there by clicking the appropriate SDK in the list on the left.

Contributing

Please do contribute! We are a fairly small developer team here at Woopra, and sometimes there are no experts in house in, say PHP or Objective-C. We may not be able to quickly update our Python SDK for Python 3, or to get our iOS SDK tracking the new device types correctly. So yeah, we love merging pull requests! (Including updating the README!) And since everything is basically an abstraction above the tracking api, developing on the SDK's is very simple and easy.

Issues? Last Resort:

If your use case just isn't supported in our SDK's or it is but the SDK just wont work with your setup or for your needs, the last resort should always be to simply use the HTTP Tracking API directly.

Suggest Edits

Intro: Javascript API

 

The Javascript Tracking API is the primary way to get data into Woopra from your website or product. The API code is loaded in the browser as the result of running the Javascript Snippet.

To use and master this simple but crucial API, perform the below tasks to understand Woopra's tracking methodology and concepts:

  • Learn about the snippet and how to place it appropriately in your code.
  • Determine what should go in your tracker config and place a call to woopra.config() right under your snippet. At the minimum, this must include your project name.
  • Learn the woopra.track() function, and how to use it to track your own custom actions. This may include determining what events are important for your business to track. See What do I track?.
  • Learn the woopra.identify() function, and how to use it to set visitor properties on visitor profiles. Also, learn how to associate each return session with a previously-seen visitor profile, using Woopra's ID system system.

The Woopra JavaScript tracking code is designed for easy customization. It can be tailored to identify website visitors and track any custom user actions across your website or application.

The functions available return the Woopra tracking object in the browser, so you can chain methods:

window.woopra.identify('testEmail@emails.com').track('my_event', {
  eventProp1: 'event prop value'
})
Suggest Edits

The Javascript Snippet

 

The Javascript Snippet is a small function placed on your webpage to initialize the Woopra tracking object and to asynchronously load the Woopra tracker code. It's typically placed in the <head> of your document. It's important to keep in mind that the Woopra tracking code runs asynchronously. This means that Woopra will load in the background while your page elements load, therefore it will not slow down the performance of your website or application.

It Snippet also defines the tracker's methods so that you can immediately set the configuration and call track() and identify(), and it will queue those calls and run them when the tracker loads.

Using the Snippet

The Pure Snippet Function

There are multiple ways in which you can customize the Javascript Snippet. Here we'll go over some general best-practices.

Below is the raw javascript snippet:

!function(){var a,b,c,d=window,e=document,f=arguments,g="script",h=["config","track","trackForm","trackClick","identify","visit","push","call"],i=function(){var a,b=this,c=function(a){b[a]=function(){return b._e.push([a].concat(Array.prototype.slice.call(arguments,0))),b}};for(b._e=[],a=0;a<h.length;a++)c(h[a])};for(d.__woo=d.__woo||{},a=0;a<f.length;a++)d.__woo[f[a]]=d[f[a]]=d[f[a]]||new i;b=e.createElement(g),b.async=1,b.src="//static.woopra.com/js/w.js",c=e.getElementsByTagName(g)[0],c.parentNode.insertBefore(b,c)}("woopra");

The snippet is an immediately-invoked function expression that asynchronously loads the javascript tracking SDK code in the browser. It also prepares some queueing so that you can make calls to the methods before the tracking code finishes loading, and will evaluate those calls when it finishes loading.

This is the minimum requirement to add to the webpage code in order to make the Woopra tracker function, however, adding this will not track any events. Rather, it will expose the config(), track(), identify(), and push() functions for you to use in your client-side javascript.

To see any data in Woopra, you need to make a call to woopra.config() to tell the tracker object the name of your project, and a call to woopra.track() to actually track an event in Woopra.

A Common Snippet and Tracking Implementation

Below is an example of installation inside the <head> of a website. It will install the tracker on every page load and track a standard built-in pageview. (See woopra.track() for more on sending the default pageview event, and Built-in Events for more on built-in events in general.)

One thing to note is that if you have a Single Page Application, the <head> section of the page may only be rendered once, thus only tracking a single pageview when in fact your visitor may perform many different app views in your web app. See our SPAs for more info on this.

<head>
  <!-- ... Your head code -->
  <script>
    //WOOPRA SNIPPET:
    //initialize tracker object on page and create queues for funciton calls
    //and async load tracker.
    !function(){var a,b,c,d=window,e=document,f=arguments,g="script",h=["config","track","trackForm","trackClick","identify","visit","push","call"],i=function(){var a,b=this,c=function(a){b[a]=function(){return b._e.push([a].concat(Array.prototype.slice.call(arguments,0))),b}};for(b._e=[],a=0;a<h.length;a++)c(h[a])};for(d.__woo=d.__woo||{},a=0;a<f.length;a++)d.__woo[f[a]]=d[f[a]]=d[f[a]]||new i;b=e.createElement(g),b.async=1,b.src="//static.woopra.com/js/w.js",c=e.getElementsByTagName(g)[0],c.parentNode.insertBefore(b,c)}("woopra"); /*This function is invoked with the tracker object name.  You can change this if you like. See below*/

    //WOOPRA TRACKER:
    // configure tracker
    //There are many options you can pass here to configure the tracker.
    //All options have sane defaults.
    //The only REQUIERD option to set is your 
    //  project name in the "domain" property
    woopra.config({
     domain: "mybusiness.com" //This is the minimum required config
    });

    // track pageview
    woopra.track(); //With no arguments, the track funciton will track a default pageview event. See docs for woopra.track() function
  </script>
  
  <!-- ... More of Your head code ... -->
</head>

Remember, the snippet on line six above is what loads the Woopra object onto the window. The calls to woopra.track() etc. are using the woopra object that the snippet loaded.

After the first call to woopra.track(), the ping will start. The ping sends requests to the Woopra tracking servers on an interval so that Woopra can determine the duration of a pageview, the length of a session/visit, etc. For more on the ping, see The Ping.

What's the difference between the snippet and the tracker?

It's important to understand the difference between the Snippet and the Tracker. The Snippet is a short simple function that loads the Tracker. The Tracker Object itself is the javascript code that sends events into Woopra.

Once installed, the snippet should never need to be changed or be updated. The snippet loads the Tracker code itself from the Woopra servers. The Tracker code may change at times based on new security concerns on the web, or new features that we may add. But when this happens, you don't have to change anything in your page to get the new tracker and features, because the snippet code loads the newest version of the tracker every time the web page is loaded on a visitor's browser.

Changing the name of the tracker object

The Snippet function takes one parameter: a string which will be the name of the tracker object on the window object. In the examples above, the string "woopra" is passed as the argument. This means that your tracker will be available on the browser at window.woopra. You can alter this if you wish. You can pass any valid javascript object parameter key string here. For example, if you want to access the tracker at window.tracker, you can invoke your snippet with `"tracker" as the argument.

When Can I Call `woopra.track()`?

The snippet begins the asynchronous task of downloading the latest Woopra tracker object, and installing it onto the window object. Because this is asynchronous, the next line that runs after the snippet is guaranteed to be executed before the tracker is loaded. That is why part of what the snippet does is prepare a set of task queues to be run once the tracker loads.

So you can call woopra.track() immediately after the line in which you place the snippet. But the tracking data will not be sent before the Woopra tracker is loaded.

If you need a callback to know when the tracker has actually completed loading, you should put a callback in your first call to woopra.track(). See the woopra.track() docs for more info.

Suggest Edits

woopra.config()

 

The config function is used to tell the tracker which project you're tracking. It also allows you to set a number of options that can affect your default pageview tracking (woopra.track() No Args!!), the behavior, domains, and locations of cookies, how the ping works, etc.

The config function supports key/value singleton argument:

woopra.config("cookie_name", "my_business_cookie");

Or an object of keys and values:

woopra.config({
    download_tracking: true,
    outgoing_tracking: true,
    ping_interval: 30000
});

Configuring your Tracker

The Woopra tracker can be customized using the config function. The config options have same defaults for normal website tracking and with exception of "domain", can usually be left un-customized.

The tracker will not work, however without a domain which is your project name in Woopra.

Find the list of options below:

Option
Default
Description

domain

N/A: required

REQUIRED Project Name in Woopra. Must be explicitly set for tracker to work.

cookie_name

"wooTracker"

Name of the cookie used to identify the visitor

cookie_domain

Website domain

Domain scope of the Woopra cookie

cookie_path

/

Directory scope of the Woopra cookie

cookie_expire

2 years from last action

Expiration date (javascript Date object) of the Woopra cookie

ping

true

Ping woopra servers to ensure that the visitor is still on the webpage

ping_interval

12000

Time interval in milliseconds between each ping

idle_timeout

300000

Idle time after which the user is considered offline

download_tracking

false

Track downloads on the web page

outgoing_tracking

false

Track external links clicks on the web page

outgoing_ignore_subdomain

true

Do not include links to subdomains as outgoing links

download_pause

200

Time in millisecond to pause the browser to ensure that the event is tracked when visitor clicks on a download url.

outgoing_pause

400

Time in millisecond to pause the browser to ensure that the event is tracked when visitor clicks on an outgoing url.

ignore_query_url

true

Ignores the query part of the url when the standard pageviews tracking function (track() with no args) is called

map_query_params

{}

Object with URL parameter keys mapped to action property names. (e.g. { ref: "campaign_name" })

hide_campaign

false

Enabling this option will remove campaign properties from the URL when they’re captured (using HTML5 pushState).

protocol

"//"
(Uses the protocol that was used to load page, i.e.: what's in the address bar)

You may use this option to force the use of https in track requests to Woopra if your page is currently loaded over http. Note that this may cause errors to print in the browser console regarding using both http and https.

Suggest Edits

woopra.track()

 

The Woopra JavaScript tracking code is designed for easy customization. It can be tailored to identify your website visitors and track any custom events across your site or application.

In order to activate tracking by Woopra’s servers, you must insert the javascript snippet into the <head> element on each page you wish to be tracked. Tracking occurs when a visitor’s Web browser executes the Woopra javascript and pings the Woopra servers. Custom visitor data, or custom events, can be added to Woopra and the reference below will demonstrate how this is done.

Javascript code is asynchronous and should be inserted in the <head> tag rather than always needing to be inserted in the page footer. By placing it in the header, the pageview will be tracked before the visitor leaves the page.

Default Pageview Event

Calling woopra.track() with no arguments sends the default built-in "pageview" event. Some of the options that you set in the tracker config are for this built-in event.

woopra.track() (No Arguments)

window.woopra.track();
 
// The line above is equivalent to:
woopra.track("pv", {
    url: window.location.pathname,
    title: document.title
});

Tracking Custom Actions

Woopra also allows you to track any type of Custom Actions in addition to pageviews. Let’s say you're running a website where visitors can signup for your service. You can track these actions using Woopra’s Custom Actions. To track custom actions, you can define the action name string and the properties associated with that action object:

woopra.track(eventName<lowercase string>, [properties]<object>, [callback]<function>)

Argument
Type
Description
eventName

String

The name of the event that you are tracking. Should be lower case

properties

Object

An object of any properties you want to track with the event

callback

Function

A callback function to run after the tracking function has been successfully received by Woopra

All event names and properties should be lowercase.

It is best practice to use _ instead of spaces.

But don't worry, you can always customize how events are displayed, described and aggregated throughout Woopra in your schemas. You can even create sentence templates using event property values for when an instance of the event is shown in the Woopra interface. Think: "James Kirk Purchased a Starship for 1000 bitcoin" from your template: ${visitor.full_name} Purchased ${action.product_name} for ${action.item_price} ${action.currency}

The Callback

Optionally, you can pass, as the last argument to woopra.track() a callback function that will be called after the tracker has received the response from the tracking server.

This can be useful if you need to access Woopra labels data (at window.woopra.labels) but only after it has been evaluated and updated by the tracking server.

You can also use this as a callback to know not only when the snippet has loaded the tracker object, but when the very first Woopra tracking action has successfully completed. Essentially it guarantees that the Woopra tracker object has been loaded which may be important even though you can in fact call woopra.track() and the other methods as soon as the snippet code has run.

Example

woopra.track("signup", {
    company: "My Business",
    username: "johndoe",
    plan: "Gold"
});

The code above will track a custom event titled “signup”, and provides some more information like the username and company of the account created. Just imagine all of the custom events that can be tracked on your website: payment, comment, logout, email, etc…

What’s even more important about custom events is that you can always run custom reports about the data you pass to Woopra, so for the example given above, you could get the number of signups by company.

Don't Forget Your Schemas

When you track custom events, remember to update your schema on Woopra. Woopra will auto-generate a schema for the first event of that name that comes in, but you can add a display name and declare the types of values passed as event properties. That will help the rest your team to identify the events being tracked and Woopra will automatically build reports out of the box based on the event properties.

Below is another example to track when people click on the play button with id="play-button":

document.getElementById("play-button").onclick = function() {
    woopra.track("play", {
        artist: "Dave Brubeck",
        song: "Take Five",
        genre: "Jazz"
    });
};
Suggest Edits

woopra.identify()

 

Identifying Customers

In order to identify a customer, you need to send their email address to Woopra as a custom visitor property. Calling identify() does not send anything to Woopra, in order to send the properties and identify the visitor, you need to call track() after you identify(), or if you do not wish to track an event, you may call woopra.push() to send a call strictly with identifying information.

All visitor properties should be lowercase

woopra.identify(visitor-properties<object>)

Argument
Type
Description
properties

Object

An object of any properties you want to save for this current visitor.

Example

// configure
woopra.config(...);
 
// Identify customer
woopra.identify({
    email: "johndoe@mybusiness.com",
    name: "John Doe",
    company: "My Business"
});
 
// track
woopra.track();

Standard attributes which will be displayed in the Woopra live visitor data include:

  • id – used as a primary identifier.
  • email – displays the visitor’s email address and it will be used as a secondary unique identifier.
  • name – displays the visitor’s full name
  • company – displays the company name or account of your customer
  • avatar – is a URL link to a visitor avatar

But you can define any attribute you like and have that detail passed from within the visitor live stream data when viewing Woopra.

Note that if you wish to identify a visitor without sending a tracking event, you can call the function push().

Suggest Edits

woopra.push()

 

When you run woopra.identify(), the SDK assigns the properties you pass to the visitor object for the next track request. The track() function will send the request with any visitor properties that have been set, and with the event name and event properties as well in the same request.

Sometimes, however, you do not want to track an event by a visitor, but only to set a property on that visitor's profile, or identify the visitor by email, ID, or phone number. In this case, you should use woopra.push()

woopra.push([callback])

Argument
Type
Description

callback

Function

A callback function to run after the tracking function has been successfully received by Woopra

Example

woopra.identify("email", "johndoe@mybusiness.com").push();
 

Running Javascript Triggers

Label Membership Information

Suggest Edits

Intro: HTTP Tracking API

The most basic way to get data into the Woopra system

 

The HTTP tracking API is the most fundamental way to track events and visitor properties into Woopra. All of the tracking SDKs use this API. It is also fairly simple. If you have any issues with one of the SDK's and its compatibility or anything else, it is quite trivial to use the HTTP Tracking API instead, and gain full control of the tracking requests that you are sending to Woopra.

Types of Tracking Data

Custom Events and Event Properties

One of the key features of Woopra is the ability to track Custom Events. Understanding custom events and custom event properties is crucial to getting a good tracking implementation, and to realizing the full power of Woopra. Custom events are tracked using the /track/ce endpoint. These properties are sent with the key prefix: ce_

Custom Visitor Data

Woopra allows you to store custom visitor data on the profiles of your visitors. You can add and set visitor properties on the visitor who performs the action you are tracking. This can be done when tracking a custom event via /track/ce , or without tracking an event by calling /track/identify. These properties are sent with the key prefix: cv_

Custom Visit Data

Woopra also allows you to set metadata that span multiple events, but are not saved on the visitor's profile. This is session or visit data. Examples of this would be device_type, browser, user-agent, etc. While these properties are built-in and thus are not prefixed, and in some cases are in fact generated from http headers, etc., you can also create custom session/visit properties by using the prefix. These properties are sent with the key prefix: cs_

Custom Data Property Prefixes: ce_, cv_, and cs_

In order to allow for fast encoding, and a flat data structure, the GET request parameters are prefixed with cX_ to denote if the item is a custom event property, a custom visitor property, or a custom session property. We do try to respond to track requests within 300ms after all.

  • Custom Event properties are prefixed with ce_
  • Custom Visitor properties are prefixed with cv_
  • Custom Session properties are prefixed with cs_

Special Fields

Parameters that do not have these prefixes are non-custom, built-in or required event metadata such as the event name itself, the timeout (how long before the session is considered over before another event occurs), the project you want to send this event to, the event timestamp, the referer, etc. For legacy reasons, the cookie (aka device id) is also sent without a prefix.

Conventional Fields

Some fields can be sent as custom event properties but will be treated specially by the woopra system. The clearest example of this is the campaign data fields. Sending ce_campaign_name will actually cause the Woopra system to recognize and display the campaign data for that event in a special way. It will also use this data in attribution reports.

Another example is the url property of a pageview event. Woopra will use this to look for utm_ tags and treat them the same as campaign_name and campaign_source event properties. Click here to learn more about campaign tags.

Url Encoding

Don't forget to url encode your property keys and values.
Note: all examples omit encoding for legibility!


Example:

Consider these request query parameters:

?project=myproject.com
  &event=bark
  &timestamp= 1492030800000
  &cv_name=Rio
  &ce_campaign_name=Teach+Speak+Command
  &ce_bark_volume=loud
  &cs_is_post_nap=true

The project, event and timestamp parameters all cary necessary or overriding event metadata. The event name, the destination project, the event timestamp to use instead of the time of receipt, etc.

The cv_name will turn into a property on the visitor's profile. That property will be called "name", and will have the value on this visitor profile of "Rio". The prefix is removed before it is actually put into your data.

The ce_bark_volume on the other hand, will be a property of this particular bark event. It will show up when you expand the event in a visitor's event timeline as "bark_volume", and will have the value set as: "loud." Similarly, the ce_campaign_name will also show up as an event property, but additionally, it will be used to report on attribution and for some UI conveniences in the Woopra app.


Event and Session Timeout

The timeout parameter (not prefixed), represents the elapsed time, starting from when this event is tracked, after which the visitor's session or visit should be considered over if no further events are tracked. It takes an integer value in milliseconds. You can prevent a session from ending without tracking another event if you send a /ping or /update request for the same visitor.

Responses

Response Codes

You will get a 2xx as a response code immediately unless your request is dropped for one of the three reasons in the "Dropped Requests" section below.

  • 200 -- Processed. Request has been received and logged
  • 202 -- Queued. Request could not be processed within 300 ms due to load, so it has been queued.
  • 401 -- Unauthorized: you have secure tracking enabled, but the request is not authenticated
  • 402 -- Over Quota: Your project has reached its quota for number of actions tracked. Tracking data is logged, but triggers are not run, and interface is locked out. Upgrade to see your data.
  • 403 -- Forbidden: Your project is not registered, or you have defined exclusions for this visitor
  • 5XX -- There has been a server error. Please double check your request format, then report to support@woopra.com.

Response Bodies

The tracking servers will usually respond with a string of javascript to be run on the browser of the visitor if possible. The Javascript client-side API, for example runs this string of code, which can invoke trigger actions from the system or AppConnect apps, as well as set metadata on the tracker object itself for access by these triggers, such as the visitors's label membership information.

Dropped Requests

Woopra's tracking servers are as forgiving as they can possibly be. There are very few reasons for which a request sent to a tracking server will be dropped and not tracked. Here they are:

  1. If there is no project in the request, or the project does not exist, the Woopra Tracking servers do no know on which Woopra instance to apply the data. In this case, the request will be dropped. The preferred parameter to send your project name in a tracking request is project, but for legacy and flexibility reasons, it will also check these parameters for a project title: domain, website, host, and alias. The Server will return a 403.

  2. If Secure Tracking is enabled and the tracking request is not secure, the tracking servers will refuse to track the event in the request. The Server will return a 401.

  3. If the visitor is excluded for instance by ip or by user-agent in your settings, Woopra will drop the request. See Excluding Visitors. The server will return a code 403.

Missing Visitor Identifiers

If there are no Visitor Identifiers for the visitor, the tracking servers do not know on which visitor profile to apply this action. Identifiers include but are not limited to: id, email, and cookie. See Woopra's Profile ID System for more-in depth discussion on visitor identifiers, and the id hierarchy.

In this case, the tracking server will usually accept the request, but will generate a random value and place it in the cookie field of the visitor. (Woopra cookies are the lowest level of id in the id hierarchy. Think of woopra cookies as a device_id).

If this happens, you will never be able to identify the user who performed the action, nor will you be able to assign more actions or visitor properties to this user.

Sending Event Timestamps

Historical Events

You may send any timestamp in the past with your event. Sending future timestamps will not work reliably. Sending old timestamps will work, and the data will be considered in it's true place in time. However, please note that sending events older than your data retention window will result in an apparent loss of those events.

Future Events

Sending events with timestamps in the future can work, but can also cause unexpected behavior. The event will be logged in the log file of the time of receipt. The data will not show up in the Woopra UI until the timestamp has passed, ie: until the event "happens."

In both cases, the larger the difference between the timestamp of the event itself and the date of the transactional db log file in which it was recorded, the more likely the event will be missed in analytics, and segment reporting. This generally happens because certain time constraints of a report cause the system to only evaluate log files of that date range. If you think you may be missing out on data when you run certain reports, reach out to support@woopra.com to get more details on this with regards to your specific situation.

Old Events

Note, that while the tracking servers will accept a well-formed request in which the timestamp is older than your data retention policy limit, you will likely never see those events in the interface.

Tid Bits

  • There is no limit on the number of the parameters, as long as your browser can handle the size of the resulting GET request.
  • It is recommended to use non-blocking http clients, especially for high volume traffic.
  • The Http client used to start the tracking requests should be able to handle 301, 302 redirects, and should preferably handle cookies.
Suggest Edits

/track/ce

To track events in Woopra, send Http GET requests to this endpoint

 

Endpoint: http(s)://www.woopra.com/track/ce

Track Requests

Track requests track an event performed by a visitor. This is the main endpoint to use, and may very well end up being the only endpoint you need to use.

GET Request Parameters

Parameter
Required
Type
Example
Description

project

Required

<string>

"my-project.com"

The name of your project in Woopra.

cookie

Optional (Recommended. See Description)

<string>

"kDei34gy3h25F"

The Cookie should be thought of as a device id. It can also be used for anonymous ids. Required if no cv_{Visitor Identifier}. See The Cookie

event

Required

<string> lowercase

"form_submit"

The name of the custom event that you are tracking. See Custom Events.

timestamp

Optional

<integer> unix ms timestamp

1489704275615

Event timestamp – time in milliseconds since the UNIX epoch that the event occurred. (this can be back-dated, but not in the future.)

cv_{Visitor Identifier}

Optional (Required to identify a user)

<string>

cv_email: "tigi@woopra.com"

An identifier or multiple identifiers to associate with this visitor. Required if no cookie. See Visitor Identifiers

cv_{Visitor Property}

Optional

Various (See Description)

cv_first_name: "Tigi"

Properties to set on the visitor's profile. These can be strings, numbers, dates, etc. See Visitor Properties

ce_{Event Property}

Optional

Various (See Description)

ce_total_value: 54

Properties to set on the custom event. These can be strings, numbers, dates, etc. See Custom Events.

cs_{Visit Property}

Optional

Various (See Description)

cs_is_work_computer: false

Properties to set on the visit/session. These can be strings, numbers, dates, etc. See Visit/Session Properties

referer

Optional

<string> valid url

"www.google.com"

Visit’s referring URL, Woopra servers will match the URL against a database of referrers and will generate a referrer type and search terms when applicable. The referrers data will be automatically accessible from the Woopra interface

ip

Optional

<string> Valid IP Address

"127.0.0.1"

IP address of the visitor. If defined, it overrides the physical IP address of the connection.

timeout

Optional

<integer> milliseconds

Default: 30000 //30 seconds

In milliseconds, defaults to 30000 (equivalent to 30 seconds) after which the event will expire and the visit will be marked as over, and the visitor as offline.

browser

Optional

<string>

"chrome"

User’s browser. If defined, it overrides the auto-detected browser from the request's user-agent. You can also build your custom user-agent.

os

Optional

<string>

"Windows 10"

User’s operating system. If defined, it overrides the auto-detected operating system from user-agent.

device

Optional

<string>

eg: "mobile" or "i-phone"

User’s device type. If defined, it overrides the auto-detected device type from user-agent. Common values are mobile, tablet and desktop.

Pageviews

Woopra has a default pageview event that the Javascript Client Tracker send when there are no arguments sent to the track function. It automatically adds certain visit and event properties such as page title, url, device resolution, etc. Here is an example of request parameters sent from the SDK for a built-in pageview event:


{
  project: "dev.woopra.com"
  instance: "woopra"
  screen: "2560x1440"
  language: "en-US"
  app: "js-client"
  referer:"www.google.com"
  cookie: "5e0saOzmYfgh4q"
  event: "pv"
  ce_title: "Real-time Customer Analytics - Woopra"
  ce_domain: "www.woopra.com"
  ce_url: "/welcome-page"
	ce_uri: "https://www.woopra.com/welcome-page"
}

To track similar pageview events via this API, it is recommended that at least ce_url is used for the page path, and ce_title is used for the page title. This will integrate seamlessly with the Woopra interface and built-in pageview event reporting.

Example

To track a payment by John Smith of $149.95 for a Titanium package, you should issue a tracking request similar to the following:

http://www.woopra.com/track/ce/
  ?host=mywebsite.com
  &response=json
  &cookie=AH47DHS5SF182DIQZJD
  &timeout=300000
  &cv_username=John+Smith
  &cv_email=john@mail.com
  &event=payment
  &ce_amount=149.95
  &ce_type=blog
  &ce_package=Titanium
Suggest Edits

/track/identify

To update visitor properties in Woopra, send Http GET requests to this endpoint

 

Endpoint: http(s)://www.woopra.com/track/identify

Identify requests

Identify requests can be used to ID a visitor and/or add properties to that visitor. The endpoint is: http(s)://www.woopra.com/track/identify and the parameters are the same as a regular tracking request (event data will be ignored)

GET Request Parameters

Parameter
Required
Type
Example
Description

project

Required

<string>

"my-project.com"

The name of your project in Woopra.

cookie

Optional (Recommended. See Description)

<string>

"kDei34gy3h25F"

The Cookie should be thought of as a device id. It can also be used for anonymous ids. Required if no cv_{Visitor Identifier}. See The Cookie

cv_{Visitor Identifier}

Optional (Required to identify a user)

<string>

cv_email: "tigi@woopra.com"

An identifier or multiple identifiers to associate with this visitor. Required if no cookie. See Visitor Identifiers

cv_{Visitor Property}

Required

Various (See Description)

cv_first_name: "Tigi"

Properties to set on the visitor's profile. These can be strings, numbers, dates, etc. See Visitor Properties

Example

curl http://www.woopra.com/track/identify\
?host=mywebsite.com\
&cookie=AH47DHS5SF182DIQZJD\
&cv_email=tigi@brembo.com\
&cv_name=Tigi\
&cv_age=31
Suggest Edits

/track/update

Used to update event properties on a previous event in this un-expired session

 

Endpoint: http(s)://www.woopra.com/track/update

Event Update Requests

It is possible to add/modify an event property after the event has been tracked. This can be useful when tracking ongoing activity such as watching a video.

http://www.woopra.com/track/update
  ?host=mywebsite.com
  &event_id=aq3IUy7489d
  &ce_duration=32
  &ce_unit=seconds

Which event is updated?

There is a order of priority for finding the event to update

  1. You can send your own uid for the original event as event_id (no prefix) when you send it and use that id to reference it in the update request.
  2. You can send the event name as event, just like you did on the original event, and the update will apply to the last event by that name that occurred in this session.
  3. Otherwise, the update will apply to the last event sent.
Suggest Edits

/track/ping

Used to reset the session timeout counter, keeping this session alive

 

Ping requests

Optionally, ping requests can be periodically sent to Woopra servers to refresh the visitor timeout counter for the session/visit. This is used if it’s important to keep a visitor status ‘online’ when she’s inactive for a long time (for cases such as watching a long video). The javascript SDK will automatically start sending pings after the first event is sent.

http://www.woopra.com/track/ping
  ?host=mywebsite.com
  &cookie=AH47DHS5SF182DIQZJD
  &timeout=300000
  • There is no need to have custom parameters in the ping request.
  • It is recommend to send ping requests at intervals slightly less than the timeout value. If the timeout is 60 seconds, consider pinging the servers every 55 seconds, otherwise you will be sending unnecessary requests.
Suggest Edits

Examples

Examples of tracking code

 

Tracking Request Examples

Track a purchase event with some visitor data, and purchase event properties

http://www.woopra.com/track/ce
  ?host=mywebsite.com
  &response=json
  &cookie=AH47DHS5SF182DIQZJD
  &timeout=300000
  &cv_name=John+Smith 
  &cv_email=john@mail.com
  &event=purchase
  &ce_item=Coffee+Machine 
  &ce_category=Electric+Appliances
  &ce_sku=K5236532
Suggest Edits

Advanced

Advanced Tracking API usage concepts and examples.

 

Custom Email Tracking

One inventive way to use our HTTP Tracking API is to use it to track your campaign email opens. You probably need to have some development experience to get this working.

Typically, to track marketing email lifecycle events, one would simply install the Woopra integration for the relevant email provider in the Integrations Interface in Woopra. But we haven't integrated with every email platform, and some email marketing tools that we have integrated with, don't have this functionality either in the tool, or in our integration specifically.

So one solution is to use our HTTP Tracking API to do some of what a fully-featured email marketing automation platform does as far as tracking email lifecycle events.

TL;DR

In short, what you will be doing is creating a an <img> tag with a source url that will in fact send data to Woopra's tracking servers. Basically a webhook to Woopra from each individual email you send.

Details

So let's say we want to track an event with this basic information in it when someone opens an email:

{
  project: "<your-woopra-project>",
  visitor: {
    email: "*|EMAIL|*", //example merge tag from madril/mailchimp
  	fname: "*|FNAME|*"
  },
  event: {
    name: "email_opened",
    params: {
      email_subject: "*|MC:SUBJECT|*",
      list_name: "*|LIST:NAME|*",
    	campaign_name: "*|CAMPAIGN_NAME|*",
      campaign_id: "*|CAMPAIGN_UID|*",
      campaign_source: "email",
      //etc.
    }
  }
}

We have used merge tags from mailchimp as examples of how to get the data from your email provider. It may be via templated values like merge tags in mandrill or mailchimp, or it may work in some other way, and you'll have to figure this out as part of getting the data into the email.

Once you know how to get all the data you want, compose the above event into a url that hits the Woopra HTTP Tracking API. The above data would look like this:

https://www.woopra.com/track/ce?
	project=woopra-project.com
  &event=email_opened
  &cv_email=*|EMAIL|*
  &cv_fname=*|FNAME|*
  &ce_email_subject=*|MC:SUBJECT|*
  &ce_list_name=*|LIST:NAME|*
  &ce_campaign_name=*|CAMPAIGN_NAME|*
  &ce_campaign_id=*|CAMPAIGN_UID|*
  &ce_campaign_source=email

Finally, You would put this into an html image tag and place that raw html into your emails (perhaps in the signature so that it is always there).

The image tag may look like this:

<img src="https://www.woopra.com/track/ce?project=woopra-project.com&event=email_opened&cv_email=*|EMAIL|*&cv_fname=*|FNAME|*&ce_email_subject=*|MC:SUBJECT|*&ce_list_name=*|LIST:NAME|*&ce_campaign_name=*|CAMPAIGN_NAME|*&ce_campaign_id=*|CAMPAIGN_UID|*&ce_campaign_source=email"/> 

Now, whenever that email is rendered, a track event will be sent to Woopra as part of that html email rendering. This won't work for email recipients who request text only emails, or cannot view html emails.

The Woopra API is mostly RESTful. We call it RESTish. API calls can be made with HTTP POST or GET to https://www.woopra.com/rest/[version]/[endpoint].

curl "https://www.woopra.com/rest/3.0/trends?project=mybusiness.com&start_day=2017-4-12&end_day=2017-5-19&report_id=83mYcoe6jX"

Authentication

The Woopra RESTish APIs use the HTTP Basic Authorization Scheme. Generate API keys on a per-user basis from the Access Keys tab in the Member's Area.

curl \
--user <App Id>:<Secret Key> \
"https://www.woopra.com/rest/3.0/trends?project=mybusiness.com&start_day=2017-4-12&end_day=2017-5-19&report_id=83mYcoe6jX"

Rate Limits

There is currently a global per-project limit on API calls:
300 per minute, 600 per hour and 3000 per day.

This is subject to change as we tune the system.

Rate limited requests will receive a status code of 429

Versioning

The only supported version currently is version 3.0. So all urls should start with:
https://www.woopra.com/rest/3.0/{ENDPOINT}

Suggest Edits

Reporting API

This is the API to use if you want to programmatically query your Woopra data as it appears in Woopra reports.

 

INCOMPLETE DOCUMENTATION

Warning: the documentation for the reporting endpoints is not complete. please refer to woopra.com/docs/ for more details on accepted and required fields.

Common Parameters

skip_drilldown

Sending skip_drilldown:false will have servers include in the response, the segment definitions (expressed in Woopra's segmentation DSL for each group of visitors that are in a funnel step in a given cohort (usually this cohort is days.) In simpler terms, this data can show you WHO is in each cell in a funnel report that you wee in the woopra interface, and is how the interface can allow you to drill down to the visitors in each cell in a report.

segments

Advanced users can programmatically define segments by which to filter their reports via the API. See Building Segments for details on creating this definition.

Suggest Edits

/people

Load people reports from your account.

 
gethttps://www.woopra.com/rest/3.0/people
curl --request GET \
  --url https://www.woopra.com/rest/3.0/people
var request = require("request");

var options = { method: 'GET', url: 'https://www.woopra.com/rest/3.0/people' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://www.woopra.com/rest/3.0/people")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://www.woopra.com/rest/3.0/people");

xhr.send(data);
import requests

url = "https://www.woopra.com/rest/3.0/people"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

No response examples available

Body Params

project
string
required

Woopra Project Name

report_id
string
required

Report ID – can be found by retrieving the last part of the URL path when loading a report in the web app. Ex: for the report https://www.woopra.com/live/project/mybusiness.com/funnels/6d9hqssf37 the report ID is: “6d9hqssf37”

limit
string

max number of records to return

offset
string

number of records to skip

 
Suggest Edits

/trends

Load trends reports from your account.

 
gethttps://www.woopra.com/rest/3.0/trends
curl --request GET \
  --url 'https://www.woopra.com/rest/3.0/trends?project=project&report_id=report_id'
var request = require("request");

var options = { method: 'GET',
  url: 'https://www.woopra.com/rest/3.0/trends',
  qs: 
   { project: 'project',
     report_id: 'report_id' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://www.woopra.com/rest/3.0/trends?project=project&report_id=report_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://www.woopra.com/rest/3.0/trends?project=project&report_id=report_id");

xhr.send(data);
import requests

url = "https://www.woopra.com/rest/3.0/trends"

querystring = {"project":"project","report_id":"report_id"}

response = requests.request("GET", url, params=querystring)

print(response.text)
A binary file was returned

You couldn't be authenticated

No response examples available

Query Params

project
string
required

Woopra Project Name

report_id
string
required

Report ID – can be found by retrieving the last part of the URL path when loading a report in the web app. Ex: for the report https://www.woopra.com/live/project/mybusiness.com/<report type>/6d9hqssf37 the report ID is: “6d9hqssf37”

limit
int32

max number of records to return

offest
int32

number of records to skip

 
Suggest Edits

/journeys

Load journey reports from your account.

 
gethttps://www.woopra.com/rest/3.0/funnels
curl --request GET \
  --url 'https://www.woopra.com/rest/3.0/funnels?project=project&report_id=report_id'
var request = require("request");

var options = { method: 'GET',
  url: 'https://www.woopra.com/rest/3.0/funnels',
  qs: 
   { project: 'project',
     report_id: 'report_id' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://www.woopra.com/rest/3.0/funnels?project=project&report_id=report_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://www.woopra.com/rest/3.0/funnels?project=project&report_id=report_id");

xhr.send(data);
import requests

url = "https://www.woopra.com/rest/3.0/funnels"

querystring = {"project":"project","report_id":"report_id"}

response = requests.request("GET", url, params=querystring)

print(response.text)
A binary file was returned

You couldn't be authenticated

No response examples available

Query Params

project
string
required

Woopra Project Name

report_id
string
required

Report ID – can be found by retrieving the last part of the URL path when loading a report in the web app. Ex: for the report https://www.woopra.com/live/project/mybusiness.com/<report type>/6d9hqssf37 the report ID is: “6d9hqssf37”

limit
int32

max number of records to return

offset
int32

number of records to skip

 
Suggest Edits

/retention

Load retention reports from your account.

 
gethttps://www.woopra.com/rest/3.0/retention
curl --request GET \
  --url 'https://www.woopra.com/rest/3.0/retention?project=project&report_id=report_id'
var request = require("request");

var options = { method: 'GET',
  url: 'https://www.woopra.com/rest/3.0/retention',
  qs: 
   { project: 'project',
     report_id: 'report_id' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://www.woopra.com/rest/3.0/retention?project=project&report_id=report_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://www.woopra.com/rest/3.0/retention?project=project&report_id=report_id");

xhr.send(data);
import requests

url = "https://www.woopra.com/rest/3.0/retention"

querystring = {"project":"project","report_id":"report_id"}

response = requests.request("GET", url, params=querystring)

print(response.text)
A binary file was returned

You couldn't be authenticated

No response examples available

Query Params

project
string
required

Woopra Project Name

report_id
string
required

Report ID – can be found by retrieving the last part of the URL path when loading a report in the web app. Ex: for the report https://www.woopra.com/live/project/mybusiness.com/<report type>/6d9hqssf37 the report ID is: “6d9hqssf37”

limit
int32

max number of records to return

offset
int32

number of records to skip

 
Suggest Edits

/analytics (deprecated)

Load legacy analytics reports from your account (deprecated)

 
gethttps://www.woopra.com/rest/3.0/analytics
curl --request GET \
  --url https://www.woopra.com/rest/3.0/analytics
var request = require("request");

var options = { method: 'GET',
  url: 'https://www.woopra.com/rest/3.0/analytics' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://www.woopra.com/rest/3.0/analytics")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://www.woopra.com/rest/3.0/analytics");

xhr.send(data);
import requests

url = "https://www.woopra.com/rest/3.0/analytics"

response = requests.request("GET", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

No response examples available

Body Params

project
string
required

Woopra Project Name

report_id
string
required

Report ID – can be found by retrieving the last part of the URL path when loading a report in the web app. Ex: for the report https://www.woopra.com/live/project/mybusiness.com/funnels/6d9hqssf37 the report ID is: “6d9hqssf37”

start_day
string
required

The start date in the format YYYY-MM-DD eg: 2017-04-12

end_day
string
required

The start date in the format YYYY-MM-DD eg: 2017-04-12

segments
string
limit
string

max number of records to return

offset
string

number of records to skip

 
Suggest Edits

Profiles API

Use these endpoints to retrieve a visitor's profile and activity data

 
Suggest Edits

Profile Retrieve

Retrieve the visits for a single profile

 
gethttps://www.woopra.com/rest/3.0/profile
curl --request GET \
  --url 'https://www.woopra.com/rest/3.0/profile?project=project&key=key&value=value'
var request = require("request");

var options = { method: 'GET',
  url: 'https://www.woopra.com/rest/3.0/profile',
  qs: 
   { project: 'project',
     key: 'key',
     value: 'value' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://www.woopra.com/rest/3.0/profile?project=project&key=key&value=value")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://www.woopra.com/rest/3.0/profile?project=project&key=key&value=value");

xhr.send(data);
import requests

url = "https://www.woopra.com/rest/3.0/profile"

querystring = {"project":"project","key":"key","value":"value"}

response = requests.request("GET", url, params=querystring)

print(response.text)
A binary file was returned

You couldn't be authenticated

No response examples available

Query Params

project
string
required

Woopra Project Name

key
string
required

Unique property name to lookup by - example pid, email, id, cookie

value
string
required

Property value to lookup by

 
Suggest Edits

Profile Activity

Retrieve the visits for a single profile

 
gethttps://www.woopra.com/rest/3.0/profile/actions
curl --request GET \
  --url 'https://www.woopra.com/rest/3.0/profile/actions?project=project&key=key&value=value'
var request = require("request");

var options = { method: 'GET',
  url: 'https://www.woopra.com/rest/3.0/profile/actions',
  qs: 
   { project: 'project',
     key: 'key',
     value: 'value' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://www.woopra.com/rest/3.0/profile/actions?project=project&key=key&value=value")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://www.woopra.com/rest/3.0/profile/actions?project=project&key=key&value=value");

xhr.send(data);
import requests

url = "https://www.woopra.com/rest/3.0/profile/actions"

querystring = {"project":"project","key":"key","value":"value"}

response = requests.request("GET", url, params=querystring)

print(response.text)
A binary file was returned

You couldn't be authenticated

No response examples available

Query Params

project
string
required

Woopra Project Name

key
string
required

Unique property name to lookup by - example pid, email, id, cookie

value
string
required

Property value to lookup by

limit
int32

Maximum number of epochs (days) - ex: limit=10 includes activity for the last 10 days

filters
json

Include only certain event names - ex: filters=["purchase"] will only return purchase events

 
Suggest Edits

Profile Delete

 
deletehttps://www.woopra.com/rest/3.0/profile/delete
curl --request DELETE \
  --url 'https://www.woopra.com/rest/3.0/profile/delete?project=project&pid=pid'
var request = require("request");

var options = { method: 'DELETE',
  url: 'https://www.woopra.com/rest/3.0/profile/delete',
  qs: 
   { project: 'project',
     pid: 'pid' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://www.woopra.com/rest/3.0/profile/delete?project=project&pid=pid")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Delete.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("DELETE", "https://www.woopra.com/rest/3.0/profile/delete?project=project&pid=pid");

xhr.send(data);
import requests

url = "https://www.woopra.com/rest/3.0/profile/delete"

querystring = {"project":"project","pid":"pid"}

response = requests.request("DELETE", url, params=querystring)

print(response.text)
A binary file was returned

You couldn't be authenticated

No response examples available

Query Params

project
string
required

Woopra Project Name

pid
string
required

The visitor's profile ID in Woopra

 
Suggest Edits

Profile Edit

 
posthttps://www.woopra.com/rest/3.0/profile/edit
curl --request POST \
  --url https://www.woopra.com/rest/3.0/profile/edit
var request = require("request");

var options = { method: 'POST',
  url: 'https://www.woopra.com/rest/3.0/profile/edit' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://www.woopra.com/rest/3.0/profile/edit")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://www.woopra.com/rest/3.0/profile/edit");

xhr.send(data);
import requests

url = "https://www.woopra.com/rest/3.0/profile/edit"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

No response examples available

Body Params

project
string
required

Woopra Project Name

pid
string
required

The visitor's profile ID in Woopra

data
json
required

The update properties in a JSON object format ex: {"first_name": "tigi", "score": 9.2}

 
Suggest Edits

Profile Actions Edit

 
posthttps://www.woopra.com/rest/3.0/profile/actions/edit
curl --request POST \
  --url https://www.woopra.com/rest/3.0/profile/actions/edit
var request = require("request");

var options = { method: 'POST',
  url: 'https://www.woopra.com/rest/3.0/profile/actions/edit' };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://www.woopra.com/rest/3.0/profile/actions/edit")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "https://www.woopra.com/rest/3.0/profile/actions/edit");

xhr.send(data);
import requests

url = "https://www.woopra.com/rest/3.0/profile/actions/edit"

response = requests.request("POST", url)

print(response.text)
A binary file was returned

You couldn't be authenticated

No response examples available

Body Params

project
string
required

Woopra Project Name

pid
string
required

The visitor's profile ID in Woopra

data
json
required

The update properties in a JSON object format ex: {"first_name": "tigi", "score": 9.2}

 
Suggest Edits

The Export API

Export raw daily visit data

 

The Export API exports a raw list of visits as line-separated JSON visit objects. You request the files by the log day in the America/Pacific time zone.

Line Types

Each line in the response is a single contained JSON object. You'll find a few different types of objects available for export. The type of object is available on the "type" key in the JSON object on each line.

Visit Lines

Visit lines represent a single session/visit for a single profile. They contain visit-level metadata, a visitor object with any updated properties for that visitor during this session, as well as an array of actions that occurred in this visit, each has its own event name, timestamp, properties, etc.

The visit also has a profile id ("pid") on which to include this visit and all of its actions. The profile id is an ephemeral randomly-generated UUID for a profile representing one person--do not rely on it to stay the same for the same person through time (see deletes below).

To process a visit line, find or create a profile in your own database with the given pid, set the keys and values from the visitor object on to this profile, then add all of the actions in the actions array to this profile.

Delete Lines

Probably the most important thing to note about this API is that, because it closely mirrors our own home-rolled, transactional database, it will include DELETE lines that are intended to nullify all previous visits for a given profile.

After a DELETE line, these visits, their actions, and all visitor data are re-logged (with the original timestamps) under a new profile id.

Delete lines are marked by type: "delete"

The most common reason for a delete is that two profiles have been identified as the same individual, and are now going to be deleted and re-logged under the same profile.

To process a delete line, find the profile in your database that you created for that pid, and delete it. It's scary, we know, but the coming lines will contain all the data you just deleted, and likely more. The delete line will also contain a new_id with the new pid that will be used to re-log these actions and any further ones for this profile, along with any actions from other merged profiles, as well as the new action that caused the merge.

Deletes? (yes, deletes).

Deleting in a transactional database is usually done by writing a delete directive. In practice, this should never result in data being erased. Rather, the data processing system reads the delete line as a directive to ignore a particular piece of data that was logged in the past. whenever reading relevant data after the delete. There are many reasons for this system in a transactional database, and Wikipedia or Stack Overflow will surely help figure them out.

So why are there so many delete actions in our particular case? Well, there are often anonymous users who come back multiple times to interact with your site, product, or in other ways but are never identified. This would result in each of these sessions being attributed to its own pid.

Consider this example:

DELETES EXAMPLE:

Let's say a user has three anonymous profiles--one from her desktop two weeks ago when she first discovered your website, one from her mobile phone where she clicked an advertisement a few days ago, and one on her work laptop a few minutes ago. She decides to create an account and identify herself today.

On her work laptop, she submits her information on your CTA form and gives you her email address. You, of course, forward that email address to Woopra to put on her profile. The export logs would now see a DELETE for the old anonymous profile id and a new one would be created that is mapped to this email address AND to the cookie on her work laptop.

So now let's say this evening, the user in question is on the train home and decides to sign in with her new email/account from her phone. When she does this, the profile that had pointed to the phone's cookie will get a DELETE, and all of those actions will be re-logged onto the new pid that was generated when she gave us her email earlier today.

This is called a profile merge, and you can learn more about these concepts as they pertain to visitor identifiers in the Woopra's Profile ID System document. The same thing will happen again when she logs in from her desktop.

The database sometimes seems to have a mind of its own when it comes to deleting. For instance, the first identify in the previous example may not have a delete after it, but just a new visitor property added to the visitor object in a "type: visit" line. Similarly, often a merge event will lead to both profiles being deleted and re-logged under a third profile.

There is no simple way to predict exact behavior, but your data is guaranteed to be consistent if you follow the rules of deleting when the system tells you to and trust that you will get the data re-logged.

Suggest Edits

/logs/export

Export Woopra logs as JSON separated lines, each line contains an entire session (visit).

 
gethttps://www.woopra.com/rest/3.0/logs/export
curl --request GET \
  --url 'https://www.woopra.com/rest/3.0/logs/export?project=project&epoch=epoch'
var request = require("request");

var options = { method: 'GET',
  url: 'https://www.woopra.com/rest/3.0/logs/export',
  qs: 
   { project: 'project',
     epoch: 'epoch' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://www.woopra.com/rest/3.0/logs/export?project=project&epoch=epoch")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://www.woopra.com/rest/3.0/logs/export?project=project&epoch=epoch");

xhr.send(data);
import requests

url = "https://www.woopra.com/rest/3.0/logs/export"

querystring = {"project":"project","epoch":"epoch"}

response = requests.request("GET", url, params=querystring)

print(response.text)
A binary file was returned

You couldn't be authenticated

No response examples available

Query Params

project
string
required

Enter the name of your Woopra project here.

epoch
date
required

Log file epoch - matches the yyyy-MM-dd epoch in PST time

pos
int64

Position of the log file in question, only relevant if getting today's logs

 

Parameters

file

To tell Woopra which file you would like to export, you simply send it the name of the log file. This is also the PST date of the log file having the format yyyy-MM-dd. Ex: 2015-02-01 is the log file for Feb 1st, 2015. Log files are rotated at midnight PST. It is a good practice to send an http HEAD request to the same endpoint to get the current log file name.

pos (Paging or Streaming)

Each response will contain two headers: X-Woopra-NextFile and X-Woopra-NextPos You can use these to programmatically determine what parameters to use for your next call so as to avoid any duplicate lines coming in.

If you are exporting today's file, you will definitely need to use the pos key to ensure that you can get data starting at the correct cursor when you make the next call. Otherwise you could get duplicate or missed events.

Suggest Edits

The Import API

Import raw visit data with actions and visitor properties

 

The Import API allow you to bulk fill events and visitor properties into your Woopra instance in a single transaction.

This endpoint accepts an http body of line-separated JSON. This means, a single JSON object represented as a string (without the outer quotes) on each line. For Example:

{"visitor":{"email":"test1@mail.com"}, "actions":[{"time":1444077951001, "name":"purchase", "properties":{"price":20, "currency":"$"}]}
{"visitor":{"email":"test2@mail.com", "username": "test2"}, "actions":[{"time":1444077951891, "name":"signup", "properties":{"campaign": true}}]}
...

Importing Visits

Each line in the body that you POST to /import should be a visit, a.k.a. session. The visit object should include a nested actions array, and a visitor object. At minimum, the visitor object should have an identifier so that Woopra knows to which person profile this visit belongs. The actions array is an array of event objects, each of which has a name, a time (in UNIX milliseconds), and a properties object with the custom event properties.

It is very conceivable that a visitor will have multiple lines in this file as they have done a number of visits, each expressed on its own line, and each containing an array of actions performed on this visit.

Bulk Updating Visitor Properties

You can bulk update visitor properties without tracking any actions by only including visitor information on each line. So each line would omit the actions array, and other visit properties, and look like:

{
  "visitor": {
    "email": "<email>",
    "account_level": "enterprise",
    "property1": "prop1Value"
  }
}

A note on generated visit properties

NOTE: while you cannot send generated visit properties when doing real-time tracking (becasue they are generated) the tracking servers do not generate these fields on imports, and thus, you can send them. Imports go straight into the events database as is (more or less) and the logic that we run before write time at the end of a normal session in real-time tracking, is not run in the case of imported sessions via this endpoint. They are written as is.

A note on Engagement

Similarly, the Woopra system does not run engagement on imported data. This means that labels, triggers, and other automations are not evaluated for imported events.

Suggest Edits

/logs/import

Import sessions into Woopra. Note this API does not wait until the import process is complete, it will schedule an import task, and return the batch id in the response. The request body expects a line separated JSON file, containing a new session/visit object in every line.

 
puthttps://www.woopra.com/rest/3.0/logs/import
curl -X PUT --user appID:secretKey 'https://www.woopra.com/rest/3.0/logs/import?project=mybusiness.com' --data-binary '{"visitor": {"email": "tigi@brembo.com"},"actions":[{"name": "article view", "time": 1450808259000,"properties": { "campaign_name":"EN_2014", "campaign_medium": "Social","campaign_source": "twitter", "uri": "http://www.my-website.com/blog/welcome","title": "welcome!"}}]}'
A binary file was returned

You couldn't be authenticated

No response examples available

Query Params

project
string
required

The project into which you would like to import logs

Body Params

mixed type
required

line-separated JSON visits

 

File format

{"visitor": {"email": "tigi@brembo.com"},"actions":[{"name": "article view", "time": 1450808259000,"properties": { "campaign_name":"EN_2014", "campaign_medium": "Social","campaign_source": "twitter", "uri": "http://www.my-website.com/blog/welcome","title": "welcome!"}}]}
\n
{"visitor": {"email": "naga@brembo.com"},"actions":[{"name": "article view", "time": 1450908259000,"properties": { "campaign_name":"EN_2016", "uri": "http://www.my-website.com/","title": "some article"}}]}
\n
...

Suggest Edits

/logs/import

After starting an import, you can check the status by calling the same endpoint with GET and the batch_id as a query parameter.

 
gethttps://www.woopra.com/rest/3.0/logs/import
curl --request GET \
  --url 'https://www.woopra.com/rest/3.0/logs/import?project=project&batch_id=batch_id'
var request = require("request");

var options = { method: 'GET',
  url: 'https://www.woopra.com/rest/3.0/logs/import',
  qs: 
   { project: 'project',
     batch_id: 'batch_id' } };

request(options, function (error, response, body) {
  if (error) throw new Error(error);

  console.log(body);
});
require 'uri'
require 'net/http'

url = URI("https://www.woopra.com/rest/3.0/logs/import?project=project&batch_id=batch_id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Get.new(url)

response = http.request(request)
puts response.read_body
var data = JSON.stringify(false);

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function () {
  if (this.readyState === this.DONE) {
    console.log(this.responseText);
  }
});

xhr.open("GET", "https://www.woopra.com/rest/3.0/logs/import?project=project&batch_id=batch_id");

xhr.send(data);
import requests

url = "https://www.woopra.com/rest/3.0/logs/import"

querystring = {"project":"project","batch_id":"batch_id"}

response = requests.request("GET", url, params=querystring)

print(response.text)
A binary file was returned

You couldn't be authenticated

No response examples available

Query Params

project
string
required

Woopra Project Name

batch_id
string
required

The id of the batch of which you want to get the status