array( 'post', 'page' ), 'tracking_mode' => 'all', 'selected_post_ids' => array(), 'business_landing_page_ids' => array(), 'exclude_administrators' => true, 'exclude_logged_in_users' => false, 'store_referrer_details' => true, 'debug_full_referrers' => true, 'store_utm_parameters' => true, 'delete_data_on_uninstall' => false, 'retention_days' => 0, 'exclude_bots' => true, 'exclude_cron' => true, 'exclude_cli' => true, 'ignore_prefetch' => true, 'key_events' => array( 'phone_click', 'email_click', 'form_submit' ), 'public_counter_enabled' => false, 'public_counter_scope' => 'site', 'public_counter_metric' => 'sessions', 'public_counter_label' => 'visits', 'public_counter_icon_color' => '#2563eb', 'public_counter_background_color' => '#ffffff', 'public_counter_background_transparent' => false, 'public_counter_border_visible' => true, 'public_counter_border_color' => '#e2e8f0', ); } /** * Get settings. * * @return array */ public static function get() { $settings = get_option( self::OPTION_NAME, array() ); if ( ! is_array( $settings ) ) { $settings = array(); } return wp_parse_args( $settings, self::defaults() ); } /** * Get one setting. * * @param string $key Setting key. * @param mixed $default Default value. * @return mixed */ public static function get_value( $key, $default = null ) { $settings = self::get(); return array_key_exists( $key, $settings ) ? $settings[ $key ] : $default; } /** * Get public post types. * * @return array */ public static function public_post_types() { $post_types = get_post_types( array( 'public' => true, ), 'objects' ); unset( $post_types['attachment'] ); return $post_types; } /** * Sanitize settings before saving. * * @param array $input Raw input. * @return array */ public static function sanitize( $input ) { $input = is_array( $input ) ? $input : array(); $defaults = self::defaults(); $available_post_types = array_keys( self::public_post_types() ); $post_types = isset( $input['post_types'] ) && is_array( $input['post_types'] ) ? array_map( 'sanitize_key', wp_unslash( $input['post_types'] ) ) : array(); $post_types = array_values( array_intersect( $post_types, $available_post_types ) ); if ( empty( $post_types ) ) { // Empty means: tracking disabled for all post types. $post_types = array_values( array_unique( $post_types ) ); } $tracking_mode = isset( $input['tracking_mode'] ) ? sanitize_key( wp_unslash( $input['tracking_mode'] ) ) : 'all'; if ( ! in_array( $tracking_mode, array( 'all', 'include', 'exclude' ), true ) ) { $tracking_mode = 'all'; } $selected_post_ids = self::sanitize_post_ids( $input['selected_post_ids'] ?? '' ); $business_landing_page_ids = self::sanitize_post_ids( $input['business_landing_page_ids'] ?? '' ); $retention_days = isset( $input['retention_days'] ) ? absint( $input['retention_days'] ) : 0; if ( ! in_array( $retention_days, array( 0, 30, 90, 180, 365 ), true ) ) { $retention_days = 0; } $key_events = isset( $input['key_events'] ) && is_array( $input['key_events'] ) ? array_map( 'sanitize_key', wp_unslash( $input['key_events'] ) ) : $defaults['key_events']; $key_events = array_values( array_intersect( $key_events, self::available_key_events() ) ); $public_counter_scope = isset( $input['public_counter_scope'] ) ? sanitize_key( wp_unslash( $input['public_counter_scope'] ) ) : 'site'; if ( ! in_array( $public_counter_scope, array( 'site', 'content' ), true ) ) { $public_counter_scope = 'site'; } $public_counter_metric = isset( $input['public_counter_metric'] ) ? sanitize_key( wp_unslash( $input['public_counter_metric'] ) ) : 'sessions'; if ( ! in_array( $public_counter_metric, array( 'sessions', 'views' ), true ) ) { $public_counter_metric = 'sessions'; } $public_counter_label = isset( $input['public_counter_label'] ) ? sanitize_text_field( wp_unslash( $input['public_counter_label'] ) ) : $defaults['public_counter_label']; if ( '' === trim( $public_counter_label ) ) { $public_counter_label = $defaults['public_counter_label']; } if ( 'sessions' === $public_counter_metric && 'views' === strtolower( trim( $public_counter_label ) ) ) { $public_counter_label = $defaults['public_counter_label']; } $public_counter_icon_color = isset( $input['public_counter_icon_color'] ) ? sanitize_hex_color( wp_unslash( $input['public_counter_icon_color'] ) ) : $defaults['public_counter_icon_color']; if ( ! $public_counter_icon_color ) { $public_counter_icon_color = $defaults['public_counter_icon_color']; } $public_counter_background_color = isset( $input['public_counter_background_color'] ) ? sanitize_hex_color( wp_unslash( $input['public_counter_background_color'] ) ) : $defaults['public_counter_background_color']; if ( ! $public_counter_background_color ) { $public_counter_background_color = $defaults['public_counter_background_color']; } $public_counter_border_color = isset( $input['public_counter_border_color'] ) ? sanitize_hex_color( wp_unslash( $input['public_counter_border_color'] ) ) : $defaults['public_counter_border_color']; if ( ! $public_counter_border_color ) { $public_counter_border_color = $defaults['public_counter_border_color']; } return array( 'post_types' => $post_types, 'tracking_mode' => $tracking_mode, 'selected_post_ids' => $selected_post_ids, 'business_landing_page_ids' => $business_landing_page_ids, 'exclude_administrators' => ! empty( $input['exclude_administrators'] ), 'exclude_logged_in_users' => ! empty( $input['exclude_logged_in_users'] ), 'store_referrer_details' => ! empty( $input['store_referrer_details'] ), 'debug_full_referrers' => ! empty( $input['debug_full_referrers'] ), 'store_utm_parameters' => ! empty( $input['store_utm_parameters'] ), 'delete_data_on_uninstall' => ! empty( $input['delete_data_on_uninstall'] ), 'retention_days' => $retention_days, 'exclude_bots' => ! empty( $input['exclude_bots'] ), 'exclude_cron' => ! empty( $input['exclude_cron'] ), 'exclude_cli' => ! empty( $input['exclude_cli'] ), 'ignore_prefetch' => ! empty( $input['ignore_prefetch'] ), 'key_events' => $key_events, 'public_counter_enabled' => ! empty( $input['public_counter_enabled'] ), 'public_counter_scope' => $public_counter_scope, 'public_counter_metric' => $public_counter_metric, 'public_counter_label' => $public_counter_label, 'public_counter_icon_color' => $public_counter_icon_color, 'public_counter_background_color' => $public_counter_background_color, 'public_counter_background_transparent' => ! empty( $input['public_counter_background_transparent'] ), 'public_counter_border_visible' => ! empty( $input['public_counter_border_visible'] ), 'public_counter_border_color' => $public_counter_border_color, ); } /** * Events that can be treated as key events. * * @return array */ public static function available_key_events() { return array( 'outbound_click', 'file_download', 'phone_click', 'email_click', 'form_start', 'form_submit', 'scroll_75', 'scroll_90', ); } /** * Sanitize comma, whitespace or newline separated post IDs. * * @param string|array $value Raw value. * @return array */ public static function sanitize_post_ids( $value ) { if ( is_array( $value ) ) { $value = implode( ',', $value ); } $value = (string) wp_unslash( $value ); $ids = preg_split( '/[\s,;]+/', $value ); if ( ! is_array( $ids ) ) { return array(); } $ids = array_filter( array_map( 'absint', $ids ) ); $ids = array_values( array_unique( $ids ) ); return $ids; } /** * Determine whether a post should be tracked. * * @param int $post_id Post ID. * @return bool */ public static function should_track_post( $post_id ) { $post_id = absint( $post_id ); $settings = self::get(); if ( ! $post_id ) { return false; } $post_type = get_post_type( $post_id ); if ( ! $post_type || ! in_array( $post_type, (array) $settings['post_types'], true ) ) { return false; } $selected = array_map( 'absint', (array) $settings['selected_post_ids'] ); if ( 'include' === $settings['tracking_mode'] ) { return in_array( $post_id, $selected, true ); } if ( 'exclude' === $settings['tracking_mode'] ) { return ! in_array( $post_id, $selected, true ); } return true; } }