summaryrefslogtreecommitdiff
blob: 5f4bf88a18ddd8e448e0b35f6a4b24ef05de4688 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
<?php
namespace Automattic\Jetpack\Plugin;

use Automattic\Jetpack\Tracking as Tracks;
use Automattic\Jetpack\Connection\Manager as Connection_Manager;

class Tracking {
	/**
	 * Tracking object.
	 *
	 * @var Tracks
	 *
	 * @access private
	 */
	private $tracking;
	/**
	 * Prevents the Tracking from being intialized more then once.
	 *
	 * @var bool
	 */
	private $initalized = false;

	public function init() {
		if ( $this->initalized ) {
			return;
		}
		$this->initalized = true;
		$this->tracking   = new Tracks( 'jetpack' );

		// For tracking stuff via js/ajax.
		add_action( 'admin_enqueue_scripts', array( $this->tracking, 'enqueue_tracks_scripts' ) );

		add_action( 'jetpack_activate_module', array( $this, 'jetpack_activate_module' ), 1, 1 );
		add_action( 'jetpack_deactivate_module', array( $this, 'jetpack_deactivate_module' ), 1, 1 );
		add_action( 'jetpack_user_authorized', array( $this, 'jetpack_user_authorized' ) );
		add_action( 'wp_login_failed', array( $this, 'wp_login_failed' ) );

		// Tracking XMLRPC server events.
		add_action( 'jetpack_xmlrpc_server_event', array( $this, 'jetpack_xmlrpc_server_event' ), 10, 4 );

		// Track that we've begun verifying the previously generated secret.
		add_action( 'jetpack_verify_secrets_begin', array( $this, 'jetpack_verify_secrets_begin' ), 10, 2 );
		add_action( 'jetpack_verify_secrets_success', array( $this, 'jetpack_verify_secrets_success' ), 10, 2 );
		add_action( 'jetpack_verify_secrets_fail', array( $this, 'jetpack_verify_secrets_fail' ), 10, 3 );

		// Universal ajax callback for all tracking events triggered via js.
		add_action( 'wp_ajax_jetpack_tracks', array( $this, 'wp_ajax_jetpack_tracks' ) );

		add_action( 'jetpack_verify_api_authorization_request_error_double_encode', array( $this, 'jetpack_verify_api_authorization_request_error_double_encode' ) );
		add_action( 'jetpack_connection_register_fail', array( $this, 'jetpack_connection_register_fail' ), 10, 2 );
		add_action( 'jetpack_connection_register_success', array( $this, 'jetpack_connection_register_success' ) );
	}

	/**
	 * Track that a specific module has been activated.
	 *
	 * @access public
	 *
	 * @param string $module Module slug.
	 */
	public function jetpack_activate_module( $module ) {
		$this->tracking->record_user_event( 'module_activated', array( 'module' => $module ) );
	}

	/**
	 * Track that a specific module has been deactivated.
	 *
	 * @access public
	 *
	 * @param string $module Module slug.
	 */
	public function jetpack_deactivate_module( $module ) {
		$this->tracking->record_user_event( 'module_deactivated', array( 'module' => $module ) );
	}

	/**
	 * Track that the user has successfully received an auth token.
	 *
	 * @access public
	 */
	public function jetpack_user_authorized() {
		$user_id = get_current_user_id();
		$anon_id = get_user_meta( $user_id, 'jetpack_tracks_anon_id', true );

		if ( $anon_id ) {
			$this->tracking->record_user_event( '_aliasUser', array( 'anonId' => $anon_id ) );
			delete_user_meta( $user_id, 'jetpack_tracks_anon_id' );
			if ( ! headers_sent() ) {
				setcookie( 'tk_ai', 'expired', time() - 1000 );
			}
		}

		$connection_manager = new Connection_Manager();
		$wpcom_user_data    = $connection_manager->get_connected_user_data( $user_id );
		if ( isset( $wpcom_user_data['ID'] ) ) {
			update_user_meta( $user_id, 'jetpack_tracks_wpcom_id', $wpcom_user_data['ID'] );
		}

		$this->tracking->record_user_event( 'wpa_user_linked', array() );
	}

	/**
	 * Track that we've begun verifying the secrets.
	 *
	 * @access public
	 *
	 * @param string $action Type of secret (one of 'register', 'authorize', 'publicize').
	 * @param \WP_User $user The user object.
	 */
	public function jetpack_verify_secrets_begin( $action, $user ) {
		$this->tracking->record_user_event( "jpc_verify_{$action}_begin", array(), $user );
	}

	/**
	 * Track that we've succeeded in verifying the secrets.
	 *
	 * @access public
	 *
	 * @param string $action Type of secret (one of 'register', 'authorize', 'publicize').
	 * @param \WP_User $user The user object.
	 */
	public function jetpack_verify_secrets_success( $action, $user ) {
		$this->tracking->record_user_event( "jpc_verify_{$action}_success", array(), $user );
	}

	/**
	 * Track that we've failed verifying the secrets.
	 *
	 * @access public
	 *
	 * @param string $action Type of secret (one of 'register', 'authorize', 'publicize').
	 * @param \WP_User $user The user object.
	 * @param \WP_Error $error Error object.
	 */
	public function jetpack_verify_secrets_fail( $action, $user, $error ) {
		$this->tracking->record_user_event(
			"jpc_verify_{$action}_fail",
			array(
				'error_code'    => $error->get_error_code(),
				'error_message' => $error->get_error_message(),
			),
			$user
		);
	}

	/**
	 * Track a failed login attempt.
	 *
	 * @access public
	 *
	 * @param string $login Username or email address.
	 */
	public function wp_login_failed( $login ) {
		require_once JETPACK__PLUGIN_DIR . 'modules/protect/shared-functions.php';
		$this->tracking->record_user_event(
			'failed_login',
			array(
				'origin_ip' => jetpack_protect_get_ip(),
				'login'     => $login,
			)
		);
	}

	/**
	 * Track a connection failure at the registration step.
	 *
	 * @access public
	 *
	 * @param string|int $error      The error code.
	 * @param \WP_Error  $registered The error object.
	 */
	function jetpack_connection_register_fail( $error, $registered ) {
		$this->tracking->record_user_event( 'jpc_register_fail', array(
			'error_code'    => $error,
			'error_message' => $registered->get_error_message()
		) );
	}

	/**
	 * Track that the registration step of the connection has been successful.
	 *
	 * @access public
	 *
	 * @param string $from The 'from' GET parameter.
	 */
	function jetpack_connection_register_success( $from ) {
		$this->tracking->record_user_event( 'jpc_register_success', array(
			'from' => $from
		) );
	}

	/**
	 * Handles the jetpack_xmlrpc_server_event action that combines several types of events that
	 * happen during request serving.
	 *
	 * @param String                   $action the action name, i.e., 'remote_authorize'.
	 * @param String                   $stage  the execution stage, can be 'begin', 'success', 'error', etc.
	 * @param Array|WP_Error|IXR_Error $parameters (optional) extra parameters to be passed to the tracked action.
	 * @param WP_User                  $user (optional) the acting user.
	 */
	public function jetpack_xmlrpc_server_event( $action, $stage, $parameters = array(), $user = null ) {

		if ( is_wp_error( $parameters ) ) {
			$parameters = array(
				'error_code'    => $parameters->get_error_code(),
				'error_message' => $parameters->get_error_message(),
			);
		} elseif ( is_a( $parameters, '\\IXR_Error' ) ) {
			$parameters = array(
				'error_code'    => $parameters->code,
				'error_message' => $parameters->message,
			);
		}

		$this->tracking->record_user_event( 'jpc_' . $action . '_' . $stage, $parameters, $user );
	}

	/**
	 * Track that the site is incorrectly double-encoding redirects from http to https.
	 *
	 * @access public
	 */
	function jetpack_verify_api_authorization_request_error_double_encode() {
		$this->tracking->record_user_event( 'error_double_encode' );
	}

	/**
	 * Universal method for for all tracking events triggered via the JavaScript client.
	 *
	 * @access public
	 */
	function wp_ajax_jetpack_tracks() {
		// Check for nonce
		if ( ! isset( $_REQUEST['tracksNonce'] ) || ! wp_verify_nonce( $_REQUEST['tracksNonce'], 'jp-tracks-ajax-nonce' ) ) {
			wp_die( 'Permissions check failed.' );
		}

		if ( ! isset( $_REQUEST['tracksEventName'] ) || ! isset( $_REQUEST['tracksEventType'] ) ) {
			wp_die( 'No valid event name or type.' );
		}

		$tracks_data = array();
		if ( 'click' === $_REQUEST['tracksEventType'] && isset( $_REQUEST['tracksEventProp'] ) ) {
			if ( is_array( $_REQUEST['tracksEventProp'] ) ) {
				$tracks_data = $_REQUEST['tracksEventProp'];
			} else {
				$tracks_data = array( 'clicked' => $_REQUEST['tracksEventProp'] );
			}
		}

		$this->tracking->record_user_event( $_REQUEST['tracksEventName'], $tracks_data );
		wp_send_json_success();
		wp_die();
	}
}