You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
322 lines
7.5 KiB
322 lines
7.5 KiB
<?php
|
|
/**
|
|
* Analytics class
|
|
*
|
|
* @package PUM
|
|
* @copyright Copyright (c) 2023, Code Atlantic LLC
|
|
*/
|
|
|
|
if ( ! defined( 'ABSPATH' ) ) {
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Controls the basic analytics methods for Popup Maker
|
|
*/
|
|
class PUM_Analytics {
|
|
|
|
/**
|
|
* Initializes analytics endpoints and data
|
|
*/
|
|
public static function init() {
|
|
if ( ! self::analytics_enabled() ) {
|
|
return;
|
|
}
|
|
|
|
add_action( 'rest_api_init', [ __CLASS__, 'register_endpoints' ] );
|
|
add_action( 'wp_ajax_pum_analytics', [ __CLASS__, 'ajax_request' ] );
|
|
add_action( 'wp_ajax_nopriv_pum_analytics', [ __CLASS__, 'ajax_request' ] );
|
|
add_filter( 'pum_vars', [ __CLASS__, 'pum_vars' ] );
|
|
}
|
|
|
|
/**
|
|
* Checks whether analytics is enabled.
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function analytics_enabled() {
|
|
$disabled = pum_get_option( 'disable_analytics' ) || popmake_get_option( 'disable_popup_open_tracking' );
|
|
|
|
return (bool) apply_filters( 'pum_analytics_enabled', ! $disabled );
|
|
}
|
|
|
|
/**
|
|
* Get a list of key pairs for each event type.
|
|
* Internally used only for meta keys.
|
|
*
|
|
* Example returns [[open,opened],[conversion,conversion]].
|
|
*
|
|
* Usage examples:
|
|
* - popup_open_count, popup_last_opened
|
|
* - popup_conversion_count, popup_last_conversion
|
|
*
|
|
* @param string $event Event key.
|
|
*
|
|
* @return mixed
|
|
*/
|
|
public static function event_keys( $event ) {
|
|
$keys = [ $event, rtrim( $event, 'e' ) . 'ed' ];
|
|
|
|
if ( 'conversion' === $event ) {
|
|
$keys[1] = 'conversion';
|
|
}
|
|
|
|
return apply_filters( 'pum_analytics_event_keys', $keys, $event );
|
|
}
|
|
|
|
/**
|
|
* Returns an array of valid event types.
|
|
*
|
|
* @return string[]
|
|
*/
|
|
public static function valid_events() {
|
|
return apply_filters( 'pum_analytics_valid_events', [ 'open', 'conversion' ] );
|
|
}
|
|
|
|
/**
|
|
* Track an event.
|
|
*
|
|
* This is called by various methods including the ajax & rest api requests.
|
|
*
|
|
* Can be used externally such as after purchase tracking.
|
|
*
|
|
* @param array $args
|
|
*/
|
|
public static function track( $args = [] ) {
|
|
if ( empty( $args['pid'] ) || $args['pid'] <= 0 ) {
|
|
return;
|
|
}
|
|
|
|
// $uuid = isset( $_COOKIE['__pum'] ) ? sanitize_text_field( $_COOKIE['__pum'] ) : false;
|
|
// $session = $uuid && isset( $_COOKIE[ $uuid ] ) ? PUM_Utils_Array::safe_json_decode( $_COOKIE[ $uuid ] ) : false;
|
|
|
|
$event = sanitize_text_field( $args['event'] );
|
|
|
|
$popup = pum_get_popup( $args['pid'] );
|
|
|
|
if ( ! pum_is_popup( $popup ) || ! in_array( $event, self::valid_events(), true ) ) {
|
|
return;
|
|
}
|
|
|
|
$popup->increase_event_count( $event );
|
|
|
|
if ( has_action( 'pum_analytics_' . $event ) ) {
|
|
do_action( 'pum_analytics_' . $event, $popup->ID, $args );
|
|
}
|
|
|
|
do_action( 'pum_analytics_event', $args );
|
|
}
|
|
|
|
/**
|
|
* Process ajax requests.
|
|
*
|
|
* Only used when WP-JSON Restful API is not available.
|
|
*/
|
|
public static function ajax_request() {
|
|
|
|
$args = wp_parse_args(
|
|
$_REQUEST,
|
|
[
|
|
'event' => null,
|
|
'pid' => null,
|
|
'method' => null,
|
|
]
|
|
);
|
|
|
|
self::track( $args );
|
|
|
|
switch ( $args['method'] ) {
|
|
case 'image':
|
|
self::serve_pixel();
|
|
break;
|
|
|
|
case 'json':
|
|
self::serve_json();
|
|
break;
|
|
|
|
default:
|
|
self::serve_no_content();
|
|
break;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* @param WP_REST_Request $request
|
|
*
|
|
* @return WP_Error|mixed
|
|
*/
|
|
public static function analytics_endpoint( WP_REST_Request $request ) {
|
|
$args = $request->get_params();
|
|
|
|
if ( ! $args || empty( $args['pid'] ) ) {
|
|
return new WP_Error( 'missing_params', __( 'Missing Parameters.' ), [ 'status' => 404 ] );
|
|
}
|
|
|
|
self::track( $args );
|
|
|
|
self::serve_no_content();
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @param $param
|
|
*
|
|
* @return bool
|
|
*/
|
|
public static function endpoint_absint( $param ) {
|
|
return is_numeric( $param );
|
|
}
|
|
|
|
/**
|
|
* Registers the analytics endpoints
|
|
*/
|
|
public static function register_endpoints() {
|
|
register_rest_route(
|
|
self::get_analytics_namespace(),
|
|
self::get_analytics_route(),
|
|
apply_filters(
|
|
'pum_analytics_rest_route_args',
|
|
[
|
|
'methods' => 'GET',
|
|
'callback' => [ __CLASS__, 'analytics_endpoint' ],
|
|
'permission_callback' => '__return_true',
|
|
'args' => [
|
|
'event' => [
|
|
'required' => true,
|
|
'description' => __( 'Event Type', 'popup-maker' ),
|
|
'type' => 'string',
|
|
],
|
|
'pid' => [
|
|
'required' => true,
|
|
'description' => __( 'Popup ID', 'popup-maker' ),
|
|
'type' => 'integer',
|
|
'validation_callback' => [ __CLASS__, 'endpoint_absint' ],
|
|
'sanitize_callback' => 'absint',
|
|
],
|
|
],
|
|
]
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Adds our analytics endpoint to pum_vars
|
|
*
|
|
* @param array $vars The current pum_vars.
|
|
* @return array The updates pum_vars
|
|
*/
|
|
public static function pum_vars( $vars = [] ) {
|
|
$vars['analytics_route'] = self::get_analytics_route();
|
|
if ( function_exists( 'rest_url' ) ) {
|
|
$vars['analytics_api'] = esc_url_raw( rest_url( self::get_analytics_namespace() ) );
|
|
} else {
|
|
$vars['analytics_api'] = false;
|
|
}
|
|
return $vars;
|
|
}
|
|
|
|
/**
|
|
* Gets the analytics namespace
|
|
*
|
|
* If bypass adblockers is enabled, will return random or custom string. If not, returns 'pum/v1'.
|
|
*
|
|
* @return string The analytics namespce
|
|
* @since 1.13.0
|
|
*/
|
|
public static function get_analytics_namespace() {
|
|
$version = 1;
|
|
$namespace = self::customize_endpoint_value( 'pum' );
|
|
return "$namespace/v$version";
|
|
}
|
|
|
|
/**
|
|
* Gets the analytics route
|
|
*
|
|
* If bypass adblockers is enabled, will return random or custom string. If not, returns 'analytics'.
|
|
*
|
|
* @return string The analytics route
|
|
* @since 1.13.0
|
|
*/
|
|
public static function get_analytics_route() {
|
|
$route = 'analytics';
|
|
return self::customize_endpoint_value( $route );
|
|
}
|
|
|
|
/**
|
|
* Customizes the endpoint value given to it
|
|
*
|
|
* If bypass adblockers is enabled, will return random or custom string. If not, returns the value given to it.
|
|
*
|
|
* @param string $value The value to, potentially, customize.
|
|
* @return string
|
|
* @since 1.13.0
|
|
*/
|
|
public static function customize_endpoint_value( $value = '' ) {
|
|
$bypass_adblockers = pum_get_option( 'bypass_adblockers', false );
|
|
if ( true === $bypass_adblockers || 1 === intval( $bypass_adblockers ) ) {
|
|
switch ( pum_get_option( 'adblock_bypass_url_method', 'random' ) ) {
|
|
case 'custom':
|
|
$value = preg_replace( '/[^a-z0-9]+/', '-', pum_get_option( 'adblock_bypass_custom_filename', $value ) );
|
|
break;
|
|
case 'random':
|
|
default:
|
|
$site_url = get_site_url();
|
|
$value = md5( $site_url . $value );
|
|
break;
|
|
}
|
|
}
|
|
return $value;
|
|
}
|
|
|
|
/**
|
|
* Creates and returns a 1x1 tracking gif to the browser.
|
|
*/
|
|
public static function serve_pixel() {
|
|
$gif = self::get_file( Popup_Maker::$DIR . 'assets/images/beacon.gif' );
|
|
header( 'Content-Type: image/gif' );
|
|
header( 'Content-Length: ' . strlen( $gif ) );
|
|
exit( $gif );
|
|
}
|
|
|
|
/**
|
|
* @param $path
|
|
*
|
|
* @return bool|string
|
|
*/
|
|
public static function get_file( $path ) {
|
|
|
|
if ( function_exists( 'realpath' ) ) {
|
|
$path = realpath( $path );
|
|
}
|
|
|
|
if ( ! $path || ! @is_file( $path ) ) {
|
|
return '';
|
|
}
|
|
|
|
return @file_get_contents( $path );
|
|
}
|
|
|
|
/**
|
|
* Returns a 204 no content header.
|
|
*/
|
|
public static function serve_no_content() {
|
|
header( 'HTTP/1.0 204 No Content' );
|
|
header( 'Content-Type: image/gif' );
|
|
header( 'Content-Length: 0' );
|
|
exit;
|
|
}
|
|
|
|
/**
|
|
* Serves a proper json response.
|
|
*
|
|
* @param mixed $data
|
|
*/
|
|
public static function serve_json( $data = 0 ) {
|
|
header( 'Content-Type: application/json' );
|
|
echo PUM_Utils_Array::safe_json_encode( $data );
|
|
exit;
|
|
}
|
|
|
|
}
|
|
|