File "Event.php"
Full Path: /home/warrior1/public_html/wp-content/plugins/facebook-for-woocommerce/includes/Events/Event.php
File size: 7.91 KB
MIME-type: text/x-php
Charset: utf-8
<?php
// phpcs:ignoreFile
/**
* Copyright (c) Facebook, Inc. and its affiliates. All Rights Reserved
*
* This source code is licensed under the license found in the
* LICENSE file in the root directory of this source tree.
*
* @package FacebookCommerce
*/
namespace SkyVerge\WooCommerce\Facebook\Events;
defined( 'ABSPATH' ) or exit;
/**
* Event object.
*
* @since 2.0.0
*/
class Event {
/**
* @var array data specific to this event instance with the same structure as the event’s payload
*
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/payload-helper
*/
protected $data = array();
/**
* Gets version information for pixel events.
*
* @return array {
* @type string source 'woocommerce'
* @type string version WooCommerce's version
* @type string pluginVersion Facebook for WooCommerce's version
* }
*/
public static function get_version_info() {
return array(
'source' => 'woocommerce',
'version' => WC()->version,
'pluginVersion' => facebook_for_woocommerce()->get_version(),
);
}
/**
* Gets the agent string for pixel events.
*
* @return string
*/
public static function get_platform_identifier() {
$info = self::get_version_info();
return "{$info['source']}-{$info['version']}-{$info['pluginVersion']}";
}
/**
* Constructor.
*
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/parameters
*
* @since 2.0.0
*
* @param array $data event data
*/
public function __construct( $data = array() ) {
$this->prepare_data( $data );
}
/**
* Provides defaults for properties if not already defined.
*
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/parameters/server-event
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/parameters/custom-data
*
* @since 2.0.0
*
* @param array $data event data
*/
protected function prepare_data( $data ) {
$this->data = wp_parse_args(
$data,
array(
'action_source' => 'website',
'event_time' => time(),
'event_id' => $this->generate_event_id(),
'event_source_url' => $this->get_current_url(),
'custom_data' => array(),
'user_data' => array(),
)
);
$this->prepare_user_data( $this->data['user_data'] );
}
/**
* Provides defaults for user properties if not already defined.
*
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/parameters/user-data
*
* @since 2.0.0
*
* @param array $data user data
*/
protected function prepare_user_data( $data ) {
$this->data['user_data'] = wp_parse_args(
$data,
array(
'client_ip_address' => $this->get_client_ip(),
'client_user_agent' => $this->get_client_user_agent(),
'click_id' => $this->get_click_id(),
'browser_id' => $this->get_browser_id(),
)
);
// Country key is not the same in pixel and CAPI events, see:
// https://developers.facebook.com/docs/facebook-pixel/advanced/advanced-matching
// https://developers.facebook.com/docs/marketing-api/conversions-api/parameters
if ( array_key_exists( 'cn', $this->data['user_data'] ) ) {
$country = $this->data['user_data']['cn'];
$this->data['user_data']['country'] = $country;
unset( $this->data['user_data']['cn'] );
}
$this->data['user_data'] = Normalizer::normalize_array( $this->data['user_data'], false );
$this->data['user_data'] = $this->hash_pii_data( $this->data['user_data'] );
}
/**
* Hashes the user data
*
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/parameters/user-data
*
* @since 2.0.3
*
* @param array $user_data user data
*
* @return array
*/
protected function hash_pii_data( $user_data ) {
$keys_to_hash = array( 'em', 'fn', 'ln', 'ph', 'ct', 'st', 'zp', 'country', 'external_id' );
foreach ( $keys_to_hash as $key ) {
if ( array_key_exists( $key, $user_data ) ) {
$user_data[ $key ] = hash( 'sha256', $user_data[ $key ], false );
}
}
return $user_data;
}
/**
* Generates a UUIDv4 unique ID for the event.
*
* @see https://stackoverflow.com/a/15875555
*
* @since 2.0.0
*
* @return string
*/
protected function generate_event_id() {
try {
$data = random_bytes( 16 );
$data[6] = chr( ord( $data[6] ) & 0x0f | 0x40 ); // set version to 0100
$data[8] = chr( ord( $data[8] ) & 0x3f | 0x80 ); // set bits 6-7 to 10
return vsprintf( '%s%s-%s-%s-%s-%s%s%s', str_split( bin2hex( $data ), 4 ) );
} catch ( \Exception $e ) {
// fall back to mt_rand if random_bytes is unavailable
return sprintf(
'%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
// 32 bits for "time_low"
mt_rand( 0, 0xffff ),
mt_rand( 0, 0xffff ),
// 16 bits for "time_mid"
mt_rand( 0, 0xffff ),
// 16 bits for "time_hi_and_version",
// four most significant bits holds version number 4
mt_rand( 0, 0x0fff ) | 0x4000,
// 16 bits, 8 bits for "clk_seq_hi_res",
// 8 bits for "clk_seq_low",
// two most significant bits holds zero and one for variant DCE1.1
mt_rand( 0, 0x3fff ) | 0x8000,
// 48 bits for "node"
mt_rand( 0, 0xffff ),
mt_rand( 0, 0xffff ),
mt_rand( 0, 0xffff )
);
}
}
/**
* Gets the current URL.
*
* @since 2.0.0
*
* @return string
*/
protected function get_current_url() {
if ( wp_doing_ajax() ) {
$url = wp_get_raw_referer();
} else {
/**
* Instead of relying on the HTTP_HOST server var, we use home_url(),
* so that we get the host configured in site options.
* Additionally, this automatically uses the correct domain when
* using Forward with the WooCommerce Dev Helper plugin.
*/
$url = home_url() . $_SERVER['REQUEST_URI'];
}
return $url;
}
/**
* Gets the client IP address.
*
* @since 2.0.0
*
* @return string
*/
protected function get_client_ip() {
return \WC_Geolocation::get_ip_address();
}
/**
* Gets the client user agent.
*
* @since 2.0.0
*
* @return string
*/
protected function get_client_user_agent() {
return ! empty( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';
}
/**
* Gets the click ID from the cookie or the query parameter.
*
* @see https://developers.facebook.com/docs/marketing-api/server-side-api/parameters/fbp-and-fbc#fbp-and-fbc-parameters
*
* @since 2.0.0
*
* @return string
*/
protected function get_click_id() {
$click_id = '';
if ( ! empty( $_COOKIE['_fbc'] ) ) {
$click_id = $_COOKIE['_fbc'];
} elseif ( ! empty( $_REQUEST['fbclid'] ) ) {
// generate the click ID based on the query parameter
$version = 'fb';
$subdomain_index = 1;
$creation_time = time();
$fbclid = $_REQUEST['fbclid'];
$click_id = "{$version}.{$subdomain_index}.{$creation_time}.{$fbclid}";
}
return $click_id;
}
/**
* Gets the browser ID from the cookie.
*
* @since 2.0.0
*
* @return string
*/
protected function get_browser_id() {
return ! empty( $_COOKIE['_fbp'] ) ? $_COOKIE['_fbp'] : '';
}
/**
* Gets the data.
*
* @since 2.0.0
*
* @return array
*/
public function get_data() {
return $this->data;
}
/**
* Gets the event ID.
*
* @since 2.0.0
*
* @return string
*/
public function get_id() {
return ! empty( $this->data['event_id'] ) ? $this->data['event_id'] : '';
}
/**
* Gets the event name.
*
* @since 2.0.0
*
* @return string
*/
public function get_name() {
return ! empty( $this->data['event_name'] ) ? $this->data['event_name'] : '';
}
/**
* Gets the user data.
*
* @since 2.0.0
*
* @return array
*/
public function get_user_data() {
return ! empty( $this->data['user_data'] ) ? $this->data['user_data'] : array();
}
/**
* Gets the event custom data.
*
* @since 2.0.0
*
* @return array
*/
public function get_custom_data() {
return ! empty( $this->data['custom_data'] ) ? $this->data['custom_data'] : array();
}
}