├── .gitignore
├── LICENSE
├── README.md
├── composer.json
└── woopra_tracker.php
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Woopra, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in
13 | all copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Track customers directly in PHP using Woopra's PHP SDK
2 |
3 | The purpose of this SDK is to allow our customers who have servers running PHP to track their users by writing only PHP code. Tracking directly in PHP will allow you to decide whether you want to track your users:
4 | - through the front-end: after configuring the tracker, identifying the user, and tracking page views and events in PHP, the SDK will generate the corresponding JavaScript code, and you will be able to print that code in your pages' headers.
5 | - through the back-end: after configuring the tracker & identifying the user, add the optional parameter TRUE to the methods track
or push
, and the PHP tracker will handle sending the data to Woopra by making HTTP Requests. By doing that, the client is never involved in the tracking process.
6 |
7 | The best way to install Woopra/Woopra-php-sdk is using [Composer](https://getcomposer.org/)
8 |
9 | ``` sh
10 | $ composer require woopra/woopra:dev-master
11 | ```
12 |
13 | The first step is to setup the tracker SDK. To do so, import the woopra_tracker.php file then configure the tracker instance as follows (replace mybusiness.com with your website as registered on Woopra):
14 | ``` php
15 | require_once('woopra_tracker.php');
16 | // require_once('vendor/autoload.php'); // for composer installation
17 | $woopra = new WoopraTracker(array("domain" => "mybusiness.com"));
18 | ```
19 | You can update your idle timeout (default: 30 seconds) by updating the timeout property in your WoopraTracker instance (NB: this could also have been done in the step above, by adding all the properties you wish to configure to the array):
20 | ``` php
21 | $woopra->config(array("idle_timeout" => 15000)); // in milliseconds
22 | ```
23 | If you don't want to keep the user online on Woopra when they don't commit any event between the last event and the idle_timeout, you can disable auto pings (auto ping only matters for front-end tracking).
24 | ``` php
25 | $woopra->config(array("ping" => false)); // default is true
26 | ```
27 | To add custom visitor properties, you should use the identify($user) function:
28 | ``` php
29 | $woopra->identify(array(
30 | "name" => "User Name",
31 | "email" => "user@company.com",
32 | "company" => "User Business"
33 | ));
34 | ```
35 | If you wish to track page views, first call track(), and finally calling js_code() in your page header will insert the woopra javascript tracker:
36 | ``` php
37 |
38 | ...
39 | track()->js_code(); ?>
40 |
41 |
42 | ```
43 | You can always track events through front-end later in the page. With all the previous steps done at once, it should look like:
44 | ``` php
45 |
46 |
47 | ...
48 | identify($user)->track()->js_code();
51 | ?>
52 |
53 |
54 | ...
55 | track("play", array(
57 | "artist" => "Dave Brubeck",
58 | "song" => "Take Five",
59 | "genre" => "Jazz"
60 | ));
61 | ?>
62 | ...
63 |
64 |
65 |
66 | ```
67 | To track a custom event through back-end, just specify the additional parameter TRUE in the track() functions.
68 | ``` php
69 | $woopra->track($event_name, $event_properties, TRUE);
70 | ```
71 | If you identify the user after the last tracking event, don't forget to push() the update to Woopra:
72 | ``` php
73 | $woopra->identify($user)->push();
74 | //or, to push through back-end:
75 | $woopra->identify($user)->push(TRUE);
76 | ```
77 | If you're only going to be tracking through the back-end, set the cookie (before the headers are sent):
78 | ``` php
79 | $woopra->set_woopra_cookie();
80 | ```
81 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "woopra/woopra",
3 | "type": "library",
4 | "description": "Woopra.com PHP Library",
5 | "keywords": ["woopra", "analytics"],
6 | "homepage": "https://github.com/Woopra/woopra-php-sdk",
7 | "authors": [
8 | {
9 | "name": "Antoine Chkaiban",
10 | "email": "antoine.chkaiban@student.ecp.fr"
11 | },
12 | {
13 | "name": "Billy Vong",
14 | "email": "billy@woopra.com"
15 | }
16 | ],
17 | "autoload": {
18 | "classmap": ["woopra_tracker.php"]
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/woopra_tracker.php:
--------------------------------------------------------------------------------
1 | "",
35 | "cookie_name" => "wooTracker",
36 | "cookie_domain" => "",
37 | "cookie_path" => "/",
38 | "ping" => true,
39 | "ping_interval" => 12000,
40 | "idle_timeout" => 300000,
41 | "download_tracking" => true,
42 | "outgoing_tracking" => true,
43 | "download_pause" => 200,
44 | "outgoing_pause" => 400,
45 | "ignore_query_url" => true,
46 | "hide_campaign" => false,
47 | "ip_address" => "",
48 | "cookie_value" => "",
49 | "app" => ""
50 | );
51 |
52 | /**
53 | * Custom configuration stack.
54 | * If the user has set up custom configuration, store it in this array. It will be sent when the tracker is ready.
55 | * @var array
56 | */
57 | private $custom_config;
58 |
59 | /**
60 | * Current configuration
61 | * Default configuration array, updated by Manual configurations.
62 | * @var array
63 | */
64 | public $current_config;
65 |
66 | /**
67 | * User array.
68 | * If the user has been identified, store his information in this array
69 | * KEYS:
70 | * email (string) – Which displays the visitor’s email address and it will be used as a unique identifier instead of cookies.
71 | * name (string) – Which displays the visitor’s full name
72 | * company (string) – Which displays the company name or account of your customer
73 | * avatar (string) – Which is a URL link to a visitor avatar
74 | * other (string) - You can define any attribute you like and have that detail passed from within the visitor live stream data when viewing Woopra
75 | * @var array
76 | */
77 | private $user;
78 |
79 | /**
80 | * Has the latest information on the user been sent to woopra?
81 | * @var boolean
82 | */
83 | private $user_up_to_date;
84 |
85 | /**
86 | * Events array stack
87 | * Each item of the stack is either:
88 | * - an empty array (if pv event)
89 | * - an array(2) (if custom event)
90 | * O (string) - the name of the event
91 | * 1 (array) - properties associated with that action
92 | * @var array
93 | */
94 | private $events;
95 |
96 | /**
97 | * Is JavaScript Tracker Ready?
98 | * @var boolean
99 | */
100 | private $tracker_ready;
101 |
102 | /**
103 | * Woopra Analytics
104 | * @param none
105 | * @return none
106 | * @constructor
107 | */
108 | function __construct($config_params = null) {
109 |
110 | //Tracker is not ready yet
111 | $this->tracker_ready = false;
112 |
113 | //Current configuration is Default
114 | $this->current_config = WoopraTracker::$default_config;
115 |
116 | //Set the default IP
117 | $this->current_config["ip_address"] = $this->get_client_ip();
118 |
119 | //Set the domain name and the cookie_domain
120 | $this->current_config["domain"] = $_SERVER["HTTP_HOST"];
121 | $this->current_config["cookie_domain"] = $_SERVER["HTTP_HOST"];
122 |
123 | //configure app ID
124 | $this->current_config["app"] = WoopraTracker::$SDK_ID;
125 | $this->custom_config = array("app" => WoopraTracker::$SDK_ID);
126 |
127 | //If configuration array was passed, configure Woopra
128 | if (isset($config_params)) {
129 | $this->config($config_params);
130 | }
131 |
132 | //Get cookie or generate a random one
133 | $this->current_config["cookie_value"] = isset($_COOKIE[$this->current_config["cookie_name"]]) ? $_COOKIE[$this->current_config["cookie_name"]] : WoopraTracker::RandomString();
134 |
135 | //We don't have any info on the user yet, so he is up to date by default.
136 | $this->user_up_to_date = true;
137 |
138 | }
139 |
140 | /**
141 | * Echoes JS code to configure the tracker
142 | * @return none
143 | */
144 | private function print_javascript_configuration() {
145 | if (isset($this->custom_config)) {
146 |
147 | ?>
148 | woopra.config(custom_config); ?>);
149 | custom_config );
152 | }
153 | }
154 |
155 | /**
156 | * Echoes JS code to identify the user with the tracker
157 | * @return none
158 | */
159 | private function print_javascript_identification() {
160 |
161 | if ( ! $this->user_up_to_date ) {
162 | ?>
163 | woopra.identify(user); ?>);
164 | user_up_to_date = true;
166 | }
167 | }
168 |
169 | /**
170 | * Echoes JS code to track custom events
171 | * @param none
172 | * @return none
173 | */
174 | private function print_javascript_events() {
175 |
176 | if (isset($this->events)) {
177 |
178 | foreach ($this->events as $event) {
179 | if(empty($event)) {
180 | ?>
181 | woopra.track();
182 |
185 | woopra.track(, );
186 | events );
191 | }
192 | }
193 |
194 | /**
195 | * Random Cookie generator in case the user doesn't have a cookie yet. Better to use a hash of the email.
196 | * @param none
197 | * @return string
198 | */
199 | private static function RandomString() {
200 | $characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
201 | $randstring = "";
202 | for ($i = 0; $i < 12; $i++) {
203 | $randstring .= $characters[rand(0, strlen($characters)-1)];
204 | }
205 | return $randstring;
206 | }
207 |
208 |
209 |
210 | /**
211 | * Prepares the http request and sends it.
212 | * @param boolean Is this a tracking event or are we just identifying a user?
213 | * @param (optional) array
214 | * @return none
215 | */
216 | private function woopra_http_request($is_tracking, $event = null) {
217 |
218 | $base_url = "http://www.woopra.com/track/";
219 |
220 | //Config params
221 | $config_params = "?host=" . urlencode($this->current_config["domain"]);
222 | $config_params .= "&cookie=" . urlencode($this->current_config["cookie_value"]);
223 | $config_params .= "&ip=" . urlencode($this->current_config["ip_address"]);
224 | $config_params .= "&timeout=" . urlencode($this->current_config["idle_timeout"]);
225 |
226 | //User params
227 | $user_params = "";
228 | if ( isset($this->user) ) {
229 | foreach($this->user as $option => $value) {
230 | if (! (empty($option) || empty($value))) {
231 | $user_params .= "&cv_" . urlencode($option) . "=" . urlencode($value);
232 | }
233 | }
234 | }
235 |
236 | //Just identifying
237 | if ( ! $is_tracking ) {
238 | $url = $base_url . "identify/" . $config_params . $user_params . "&app=" . $this->current_config["app"];
239 |
240 | //Tracking
241 | } else {
242 |
243 | //Event params
244 | $event_params = "";
245 | if ( $event != null ) {
246 | $event_params .= "&event=" . urlencode($event[0]);
247 | foreach($event[1] as $option => $value) {
248 | if (! (empty($option) || empty($value))) {
249 | $event_params .= "&ce_" . urlencode($option) . "=" . urlencode($value);
250 | //also add referrer without prefix for woopra to pick up
251 | if ($option == "referer" || $option == "referrer") {
252 | $event_params .= "&referer=" . urlencode($value);
253 | }
254 | }
255 | }
256 | } else {
257 | $event_params .= "&event=pv&ce_url=" . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
258 | }
259 | $url = $base_url . "ce/" . $config_params . $user_params . $event_params . "&app=" . $this->current_config["app"];
260 | }
261 |
262 | //Send the request
263 | if (function_exists('curl_version')) {
264 | $this->get_data($url);
265 | } else {
266 | $opts = array(
267 | 'http'=>array(
268 | 'method'=>"GET",
269 | 'header'=>"User-Agent: ".$_SERVER['HTTP_USER_AGENT']
270 | )
271 | );
272 | $context = stream_context_create($opts);
273 | file_get_contents( $url, false, $context);
274 | }
275 |
276 | }
277 |
278 | /**
279 | * Echoes Woopra Widget JS code, and checks if there is any stored Configuration, Identification, or Custom events awaiting process and echoes it too.
280 | * @param none
281 | * @return Woopra object
282 | */
283 | public function js_code() {
284 |
285 | ?>
286 |
287 |
288 |
308 |
309 |
310 | custom_config)) {
323 | $this->custom_config = array();
324 | }
325 | foreach( $args as $option => $value) {
326 |
327 | if ( array_key_exists($option, WoopraTracker::$default_config) ) {
328 |
329 | if ( gettype($value) == gettype( WoopraTracker::$default_config[$option] ) ) {
330 | if ($option != "ip_address" && $option != "cookie_value") {
331 | $this->custom_config[$option] = $value;
332 | }
333 | $this->current_config[$option] = $value;
334 | //If the user is customizing the name of the cookie, check again if the user already has one.
335 | if ($option == "cookie_name") {
336 | $this->current_config["cookie_value"] = isset($_COOKIE[$this->current_config["cookie_name"]]) ? $_COOKIE[$this->current_config["cookie_name"]] : $this->current_config["cookie_value"];
337 | }
338 | }
339 | else {
340 | trigger_error("Wrong value type in configuration array for parameter ".$option.". Recieved ".gettype($value).", expected ".gettype( WoopraTracker::$default_config[$option] ).".");
341 | }
342 | }
343 | else {
344 | trigger_error("Unexpected parameter in configuration array: ".$option.".");
345 | }
346 | }
347 | return $this;
348 | }
349 |
350 | /**
351 | * Identifies User
352 | * @param array
353 | * @return Woopra object
354 | */
355 | public function identify($identified_user, $override = false) {
356 | if (!empty($identified_user)) {
357 | $this->user = $identified_user;
358 | $this->user_up_to_date = false;
359 |
360 | if(isset($identified_user["email"]) && ! empty($identified_user["email"])) {
361 | if ($override || !isset($_COOKIE[$this->current_config["cookie_name"]])) {
362 | $this->current_config["cookie_value"] = crc32($identified_user["email"]);
363 | }
364 | }
365 | return $this;
366 | }
367 | }
368 |
369 | /**
370 | * Tracks Custom Event. If no parameters are specified, will simply track pageview.
371 | * @param string
372 | * @param array
373 | * @param (optional) boolean
374 | * @return Woopra object
375 | */
376 | public function track($event = null, $args = array(), $back_end_processing = false) {
377 |
378 | if ( $back_end_processing ) {
379 | $http_event = null;
380 | if ( $event != null ) {
381 | $http_event = array($event, $args);
382 | }
383 | $this->woopra_http_request(true, $http_event);
384 | return $this;
385 | }
386 |
387 | if ($event == null) {
388 | if ( $this->tracker_ready ) {
389 | ?>
390 |
397 | events) ) {
400 | $this->events = array();
401 | }
402 | array_push( $this->events, array());
403 | }
404 | return $this;
405 | }
406 |
407 | if (! isset($this->events) ) {
408 | $this->events = array();
409 | }
410 | array_push( $this->events, array($event, $args) );
411 |
412 | if ( $this->tracker_ready ) {
413 | ?>
414 |
421 | woopra_http_request(false);
436 | $this->user_up_to_date = true;
437 | } elseif($this->tracker_ready) {
438 |
439 | ?>
440 |
447 | current_config["cookie_name"], $this->current_config["cookie_value"], time()+(60*60*24*365*2), $this->current_config["cookie_path"], $this->current_config["cookie_domain"] );
458 | }
459 |
460 | /**
461 | * Retrieves the user's IP address
462 | * @param none
463 | * @return String
464 | */
465 | private function get_client_ip() {
466 | if (isset($_SERVER["HTTP_X_FORWARDED_FOR"])) {
467 | $ips = explode(",", $_SERVER["HTTP_X_FORWARDED_FOR"]);
468 | return trim($ips[0]);
469 | } else {
470 | return $_SERVER["REMOTE_ADDR"];
471 | }
472 | }
473 |
474 | /**
475 | * Gets the data from a URL using CURL
476 | * @param String
477 | * @return String
478 | */
479 | private function get_data($url) {
480 | $ch = curl_init();
481 | $timeout = 5;
482 | curl_setopt($ch, CURLOPT_URL, $url);
483 | curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
484 | curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $timeout);
485 | curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
486 | $data = curl_exec($ch);
487 | curl_close($ch);
488 | return $data;
489 | }
490 | }
491 |
492 | ?>
493 |
--------------------------------------------------------------------------------