summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/jetpack/_inc/lib/tracks/class.tracks-client.php')
-rw-r--r--plugins/jetpack/_inc/lib/tracks/class.tracks-client.php191
1 files changed, 191 insertions, 0 deletions
diff --git a/plugins/jetpack/_inc/lib/tracks/class.tracks-client.php b/plugins/jetpack/_inc/lib/tracks/class.tracks-client.php
new file mode 100644
index 00000000..b83c94f1
--- /dev/null
+++ b/plugins/jetpack/_inc/lib/tracks/class.tracks-client.php
@@ -0,0 +1,191 @@
+<?php
+
+/**
+ * Jetpack_Tracks_Client
+ * @autounit nosara tracks-client
+ *
+ * Send Tracks events on behalf of a user
+ *
+ * Example Usage:
+```php
+ require( dirname(__FILE__).'path/to/tracks/class.tracks-client' );
+
+ $result = Jetpack_Tracks_Client::record_event( array(
+ '_en' => $event_name, // required
+ '_ui' => $user_id, // required unless _ul is provided
+ '_ul' => $user_login, // required unless _ui is provided
+
+ // Optional, but recommended
+ '_ts' => $ts_in_ms, // Default: now
+ '_via_ip' => $client_ip, // we use it for geo, etc.
+
+ // Possibly useful to set some context for the event
+ '_via_ua' => $client_user_agent,
+ '_via_url' => $client_url,
+ '_via_ref' => $client_referrer,
+
+ // For user-targeted tests
+ 'abtest_name' => $abtest_name,
+ 'abtest_variation' => $abtest_variation,
+
+ // Your application-specific properties
+ 'custom_property' => $some_value,
+ ) );
+
+ if ( is_wp_error( $result ) ) {
+ // Handle the error in your app
+ }
+```
+ */
+
+require_once( dirname(__FILE__).'/class.tracks-client.php' );
+
+class Jetpack_Tracks_Client {
+ const PIXEL = 'https://pixel.wp.com/t.gif';
+ const BROWSER_TYPE = 'php-agent';
+ const USER_AGENT_SLUG = 'tracks-client';
+ const VERSION = '0.3';
+
+ /**
+ * record_event
+ * @param mixed $event Event object to send to Tracks. An array will be cast to object. Required.
+ * Properties are included directly in the pixel query string after light validation.
+ * @return mixed True on success, WP_Error on failure
+ */
+ static function record_event( $event ) {
+ if ( ! Jetpack::jetpack_tos_agreed() || ! empty( $_COOKIE['tk_opt-out'] ) ) {
+ return false;
+ }
+
+ if ( ! $event instanceof Jetpack_Tracks_Event ) {
+ $event = new Jetpack_Tracks_Event( $event );
+ }
+ if ( is_wp_error( $event ) ) {
+ return $event;
+ }
+
+ $pixel = $event->build_pixel_url( $event );
+
+ if ( ! $pixel ) {
+ return new WP_Error( 'invalid_pixel', 'cannot generate tracks pixel for given input', 400 );
+ }
+
+ return self::record_pixel( $pixel );
+ }
+
+ /**
+ * Synchronously request the pixel
+ */
+ static function record_pixel( $pixel ) {
+ // Add the Request Timestamp and URL terminator just before the HTTP request.
+ $pixel .= '&_rt=' . self::build_timestamp() . '&_=_';
+
+ $response = wp_remote_get( $pixel, array(
+ 'blocking' => true, // The default, but being explicit here :)
+ 'timeout' => 1,
+ 'redirection' => 2,
+ 'httpversion' => '1.1',
+ 'user-agent' => self::get_user_agent(),
+ ) );
+
+ if ( is_wp_error( $response ) ) {
+ return $response;
+ }
+
+ $code = isset( $response['response']['code'] ) ? $response['response']['code'] : 0;
+
+ if ( $code !== 200 ) {
+ return new WP_Error( 'request_failed', 'Tracks pixel request failed', $code );
+ }
+
+ return true;
+ }
+
+ static function get_user_agent() {
+ return Jetpack_Tracks_Client::USER_AGENT_SLUG . '-v' . Jetpack_Tracks_Client::VERSION;
+ }
+
+ /**
+ * Build an event and return its tracking URL
+ * @deprecated Call the `build_pixel_url` method on a Jetpack_Tracks_Event object instead.
+ * @param array $event Event keys and values
+ * @return string URL of a tracking pixel
+ */
+ static function build_pixel_url( $event ) {
+ $_event = new Jetpack_Tracks_Event( $event );
+ return $_event->build_pixel_url();
+ }
+
+ /**
+ * Validate input for a tracks event.
+ * @deprecated Instantiate a Jetpack_Tracks_Event object instead
+ * @param array $event Event keys and values
+ * @return mixed Validated keys and values or WP_Error on failure
+ */
+ private static function validate_and_sanitize( $event ) {
+ $_event = new Jetpack_Tracks_Event( $event );
+ if ( is_wp_error( $_event ) ) {
+ return $_event;
+ }
+ return get_object_vars( $_event );
+ }
+
+ // Milliseconds since 1970-01-01
+ static function build_timestamp() {
+ $ts = round( microtime( true ) * 1000 );
+ return number_format( $ts, 0, '', '' );
+ }
+
+ /**
+ * Grabs the user's anon id from cookies, or generates and sets a new one
+ *
+ * @return string An anon id for the user
+ */
+ static function get_anon_id() {
+ static $anon_id = null;
+
+ if ( ! isset( $anon_id ) ) {
+
+ // Did the browser send us a cookie?
+ if ( isset( $_COOKIE[ 'tk_ai' ] ) && preg_match( '#^[A-Za-z0-9+/=]{24}$#', $_COOKIE[ 'tk_ai' ] ) ) {
+ $anon_id = $_COOKIE[ 'tk_ai' ];
+ } else {
+
+ $binary = '';
+
+ // Generate a new anonId and try to save it in the browser's cookies
+ // Note that base64-encoding an 18 character string generates a 24-character anon id
+ for ( $i = 0; $i < 18; ++$i ) {
+ $binary .= chr( mt_rand( 0, 255 ) );
+ }
+
+ $anon_id = 'jetpack:' . base64_encode( $binary );
+
+ if ( ! headers_sent()
+ && ! ( defined( 'REST_REQUEST' ) && REST_REQUEST )
+ && ! ( defined( 'XMLRPC_REQUEST' ) && XMLRPC_REQUEST )
+ ) {
+ setcookie( 'tk_ai', $anon_id );
+ }
+ }
+ }
+
+ return $anon_id;
+ }
+
+ /**
+ * Gets the WordPress.com user's Tracks identity, if connected.
+ *
+ * @return array|bool
+ */
+ static function get_connected_user_tracks_identity() {
+ if ( ! $user_data = Jetpack::get_connected_user_data() ) {
+ return false;
+ }
+
+ return array(
+ 'userid' => $user_data['ID'],
+ 'username' => $user_data['login'],
+ );
+ }
+}