Plugin Directory

Changeset 2270638


Ignore:
Timestamp:
03/30/2020 10:02:06 AM (6 years ago)
Author:
humcommerce
Message:

Remove E-commerce Integration and Update Readme

Location:
humcommerce/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • humcommerce/trunk/README.txt

    r2262445 r2270638  
    145145== Changelog ==
    146146
     147Ver 2.1.14 (27 Mar 2020)
     148* Fix : Removed e-commerce integration.
     149
    147150Ver 2.1.13 (24 Dec 2019)
    148151* Feature : Added a functionality to install the plugin automatically in OnBoarding process of HumCommerce Application.
  • humcommerce/trunk/humcommerce-functions.php

    r2022506 r2270638  
    55}
    66
    7 add_action('wp', 'init');
    8 
    9 function init()
    10 {
    11     if ( is_plugin_active('woocommerce/woocommerce.php'))
    12     {
    13         if (is_product()) {
    14             $product = get_page_by_path(get_post()->post_name, OBJECT, 'product');
    15             if (!empty($product)) {
    16                 $product = wc_get_product($product);
    17                 $categoryTerms = get_the_terms($product->get_id(), 'product_cat');
    18                 $categoryArray = get_categories_array($categoryTerms);
    19             }
    20             $pCode = '
    21         _ha.push(["setEcommerceView",
    22                         "' . $product->get_sku() . '",
    23                         "' . $product->get_title() . '",
    24                         [' . $categoryArray . '],
    25                         ' . get_post_meta($product->get_id(), '_price', true) . '
    26                         ]);';
    27             update_option('humcommerce_product_view', $pCode);
    28         }
    29 
    30         if (is_product_category()) {
    31             $cCode = '
    32         _ha.push(["setEcommerceView",
    33         productSku = false,
    34         productName = false,
    35         category = "' . single_cat_title("", false) . '"
    36         ]);';
    37             update_option('humcommerce_category_view', $cCode);
    38         }
    39     }
    40 
    41 }
    427
    438add_action('wp_head', 'add_humcommerce_script_to_wp_head');
    44 add_action('woocommerce_add_to_cart', 'track_update_cart', 99999, 0);
    45 add_action('woocommerce_cart_item_removed', 'track_update_cart', 99999, 0);
    46 add_action('woocommerce_cart_item_restored', 'track_update_cart', 99999, 0);
    47 add_filter('woocommerce_update_cart_action_cart_updated', 'track_update_cart_updated', 99999, 1);
    48 add_action('woocommerce_applied_coupon', 'track_update_cart', 99999, 0);
    49 add_action('woocommerce_removed_coupon', 'track_update_cart', 99999, 0);
    50 add_action('woocommerce_order_status_completed', 'track_ecommerce_order');
    519
    5210function add_humcommerce_script_to_wp_head()
     
    5917                  _ha.push(['enableLinkTracking']);
    6018                  (function() {
    61                     var u=\"//app.humdash.com/\";
     19                    var u=\"//app.humcommerce.com/\";
    6220                    _ha.push(['setTrackerUrl', u+'humdash.php']);
    6321                    _ha.push(['setSiteId', '" . $options["si"] . "']);
    6422                  })();
    6523                </script>
    66                 <script type=\"text/javascript\" src=\"//app.humdash.com/humdash.js\"></script>
     24                <script type=\"text/javascript\" src=\"//app.humcommerce.com/humdash.js\"></script>
    6725           <!-- End HumDash Code -->";
    6826    delete_option('humcommerce_add_to_cart');
     
    7230}
    7331
    74 function track_update_cart()
    75 {
    76     global $woocommerce;
    77     $items = $woocommerce->cart->get_cart();
    78     $code = '';
    79     foreach ($items as $item => $values) {
    80         $_product = wc_get_product($values['data']->get_id());
    81         $categoryTerms = get_the_terms($values['data']->get_id(), 'product_cat');
    82         $categoryArray = get_categories_array($categoryTerms);
    83         $code .= '
    84         _ha.push(["addEcommerceItem",
    85                         "' . $_product->get_sku() . '",
    86                         "' . $_product->get_title() . '",
    87                         [' . $categoryArray . '],
    88                         ' . get_post_meta($values['product_id'], '_price', true) . ',
    89                         ' . $values['quantity'] . '
    90                         ]);';
    91         update_option('humcommerce_add_to_cart', $code);
    92     }
    93 
    94     $total = 0;
    95     $cart = $woocommerce->cart;
    96     if (!empty($cart->total)) {
    97         $total = $cart->total;
    98     } elseif (!empty($cart->cart_contents_total)) {
    99         $total = $cart->cart_contents_total;
    100     }
    101     $code .= '
    102     _ha.push(["trackEcommerceCartUpdate",' . $total . ']);';
    103     update_option('humcommerce_add_to_cart', $code);
    104 }
    105 
    106 function track_update_cart_updated($cart_updated)
    107 {
    108     track_update_cart();
    109     return $cart_updated;
    110 }
    111 
    112 function track_ecommerce_order($orderId)
    113 {
    114     $code = '';
    115     $order = wc_get_order($orderId);
    116     $orderNumberToTrack = $orderId;
    117     if (method_exists($order, 'get_order_number')) {
    118         $orderNumberToTrack = $order->get_order_number();
    119     }
    120 
    121     foreach ($order->get_items() as $item_key => $item_values) {
    122         $product = $item_values->get_product();
    123 
    124         $item_data = $item_values->get_data();
    125 
    126         $product_name = $item_data['name'];
    127         $product_id = $item_data['product_id'];
    128         $categoryTerms = get_the_terms($product_id, 'product_cat');
    129         $categoryArray = get_categories_array($categoryTerms);
    130         $quantity = $item_data['quantity'];
    131         $product_sku = $product->get_sku();
    132         $product_price = $product->get_price();
    133         $code .= '_ha.push(["addEcommerceItem",
    134                         "' . $product_sku . '",
    135                         "' . $product_name . '",
    136                         [' . $categoryArray . '],
    137                         ' . $product_price . ',
    138                         ' . $quantity . '
    139                         ]);';
    140     }
    141 
    142     $shippingAmt = woocommerceVersion3() ? $order->get_shipping_total() : $order->get_total_shipping();
    143     $code .= '_ha.push(["trackEcommerceOrder",
    144                 "' . $orderNumberToTrack . '",
    145                 ' . $order->get_total() . ',
    146                 ' . $order->get_subtotal() . ',
    147                 ' . $order->get_cart_tax() . ',
    148                 ' . $shippingAmt . ',
    149                 ' . $order->get_total_discount() . '
    150                 ]);';
    151     update_option('humcommerce_track_order', $code);
    152 }
    153 
    154 function woocommerceVersion3()
    155 {
    156     global $woocommerce;
    157     $result = version_compare($woocommerce->version, '3.0', '>=');
    158     return $result;
    159 }
    160 
    161 function get_categories_array($categoryTerms){
    162     $categories = array();
    163     if (is_wp_error($categoryTerms)) {
    164         return $categories;
    165     }
    166     if (!empty($categoryTerms)) {
    167         foreach ($categoryTerms as $category) {
    168             $categories[] = $category->name;
    169         }
    170     }
    171     $categories = array_unique($categories);
    172     $categories = array_slice($categories, 0, 5);
    173     $categoryArray = '';
    174     foreach ($categories as $category) {
    175         $categoryArray .= '"' . $category . '",';
    176     }
    177     return $categoryArray;
    178 }
  • humcommerce/trunk/includes/class-humcommerce.php

    r2217514 r2270638  
    141141
    142142        $this->loader->add_action( 'wp_head', $plugin_public, 'add_humcommerce_script_to_wp_head' );
    143         $this->loader->add_action( 'woocommerce_add_to_cart', $plugin_public, 'track_update_cart', 99999, 0 );
    144         $this->loader->add_action( 'woocommerce_cart_item_removed', $plugin_public, 'track_update_cart', 99999, 0 );
    145         $this->loader->add_action( 'woocommerce_cart_item_restored', $plugin_public, 'track_update_cart', 99999, 0 );
    146         $this->loader->add_filter( 'woocommerce_update_cart_action_cart_updated', $plugin_public, 'track_update_cart_updated', 99999, 1 );
    147         $this->loader->add_action( 'woocommerce_applied_coupon', $plugin_public, 'track_update_cart', 99999, 0 );
    148         $this->loader->add_action( 'woocommerce_removed_coupon', $plugin_public, 'track_update_cart', 99999, 0 );
    149         $this->loader->add_action( 'woocommerce_thankyou', $plugin_public, 'track_ecommerce_order' );
    150143    }
    151144
  • humcommerce/trunk/libs/class-humdashtracker.php

    r2217514 r2270638  
    374374        return $this;
    375375    }
    376     /**
    377      * Sets the country of the visitor. If not used, Humdash will try to find the country
    378      * using either the visitor's IP address or language.
    379      *
    380      * Allowed only for Admin/Super User, must be used along with set_token_auth().
    381      *
    382      * @param string $country Country name or shortcode.
    383      * @return $this
    384      */
    385     public function set_country( $country ) {
    386         $this->country = $country;
    387         return $this;
    388     }
    389     /**
    390      * Sets the region of the visitor. If not used, Humdash may try to find the region
    391      * using the visitor's IP address (if configured to do so).
    392      *
    393      * Allowed only for Admin/Super User, must be used along with set_token_auth().
    394      *
    395      * @param string $region Region code or name.
    396      * @return $this
    397      */
    398     public function set_region( $region ) {
    399         $this->region = $region;
    400         return $this;
    401     }
    402     /**
    403      * Sets the city of the visitor. If not used, Humdash may try to find the city
    404      * using the visitor's IP address (if configured to do so).
    405      *
    406      * Allowed only for Admin/Super User, must be used along with set_token_auth().
    407      *
    408      * @param string $city City name or code.
    409      * @return $this
    410      */
    411     public function set_city( $city ) {
    412         $this->city = $city;
    413         return $this;
    414     }
    415     /**
    416      * Sets the latitude of the visitor. If not used, Humdash may try to find the visitor's
    417      * latitude using the visitor's IP address (if configured to do so).
    418      *
    419      * Allowed only for Admin/Super User, must be used along with set_token_auth().
    420      *
    421      * @param float $lat Latitude.
    422      * @return $this
    423      */
    424     public function set_latitude( $lat ) {
    425         $this->lat = $lat;
    426         return $this;
    427     }
    428     /**
    429      * Sets the longitude of the visitor. If not used, Humdash may try to find the visitor's
    430      * longitude using the visitor's IP address (if configured to do so).
    431      *
    432      * Allowed only for Admin/Super User, must be used along with set_token_auth().
    433      *
    434      * @param float $long Longitude.
    435      * @return $this
    436      */
    437     public function set_longitude( $long ) {
    438         $this->long = $long;
    439         return $this;
    440     }
    441     /**
    442      * Enables the bulk request feature. When used, each tracking action is stored until the
    443      * do_bulk_track method is called. This method will send all tracking data at once.
    444      */
    445     public function enable_bulk_tracking() {
    446         $this->do_bulk_requests = true;
    447     }
    448     /**
    449      * Enable Cookie Creation - this will cause a first party VisitorId cookie to be set when the VisitorId is set or reset
    450      *
    451      * @param string $domain (optional) Set first-party cookie domain.
    452      *  Accepted values: example.com, *.example.com (same as .example.com) or subdomain.example.com.
    453      * @param string $path (optional) Set first-party cookie path.
    454      */
    455     public function enable_cookies( $domain = '', $path = '/' ) {
    456         $this->config_cookies_disabled = false;
    457         $this->config_cookie_domain    = self::domain_fixup( $domain );
    458         $this->config_cookie_path      = $path;
    459     }
    460     /**
    461      * If image response is disabled Humdash will respond with a HTTP 204 header instead of responding with a gif.
    462      */
    463     public function disable_send_image_response() {
    464         $this->send_image_response = false;
    465     }
    466     /**
    467      * Fix-up domain
    468      *
    469      * @param string $domain Domain.
    470      */
    471     protected static function domain_fixup( $domain ) {
    472         if ( strlen( $domain ) > 0 ) {
    473             $dl = strlen( $domain ) - 1;
    474             // remove trailing '.'.
    475             if ( '.' === $domain{$dl} ) {
    476                 $domain = substr( $domain, 0, $dl );
    477             }
    478             // remove leading '*'.
    479             if ( substr( $domain, 0, 2 ) === '*.' ) {
    480                 $domain = substr( $domain, 1 );
    481             }
    482         }
    483         return $domain;
    484     }
     376
    485377    /**
    486378     * Get cookie name with prefix and domain hash
     
    500392        return self::FIRST_PARTY_COOKIES_PREFIX . $cookie_name . '.' . $this->idsite . '.' . $hash;
    501393    }
    502     /**
    503      * Tracks a page view
    504      *
    505      * @param string $document_title Page title as it will appear in the Actions > Page titles report.
    506      * @return mixed Response string or true if using bulk requests.
    507      */
    508     public function do_track_page_view( $document_title ) {
    509         $this->generate_new_pageview_id();
    510         $url = $this->get_url_track_page_view( $document_title );
    511         return $this->send_request( $url );
    512     }
    513 
    514     /**
    515      * Generates new page view id
    516      */
    517     private function generate_new_pageview_id() {
    518         $this->id_pageview = substr( md5( uniqid( wp_rand(), true ) ), 0, 6 );
    519     }
    520     /**
    521      * Tracks an event
    522      *
    523      * @param string      $category The Event Category (Videos, Music, Games...).
    524      * @param string      $action The Event's Action (Play, Pause, Duration, Add Playlist, Downloaded, Clicked...).
    525      * @param string|bool $name (optional) The Event's object Name (a particular Movie name, or Song name, or File name...).
    526      * @param float|bool  $value (optional) The Event's value.
    527      * @return mixed Response string or true if using bulk requests.
    528      */
    529     public function do_track_event( $category, $action, $name = false, $value = false ) {
    530         try {
    531             $url = $this->get_url_track_event( $category, $action, $name, $value );
    532         } catch ( Exception $e ) {
    533             $e->getMessage();
    534         }
    535 
    536         return $this->send_request( $url );
    537     }
    538     /**
    539      * Tracks a content impression
    540      *
    541      * @param string      $content_name The name of the content. For instance 'Ad Foo Bar'.
    542      * @param string      $content_piece The actual content. For instance the path to an image, video, audio, any text.
    543      * @param string|bool $content_target (optional) The target of the content. For instance the URL of a landing page.
    544      * @return mixed Response string or true if using bulk requests.
    545      */
    546     public function do_track_content_impression( $content_name, $content_piece = 'Unknown', $content_target = false ) {
    547         try {
    548             $url = $this->get_url_track_content_impression( $content_name, $content_piece, $content_target );
    549         } catch ( Exception $e ) {
    550             $e->getMessage();
    551         }
    552 
    553         return $this->send_request( $url );
    554     }
    555     /**
    556      * Tracks a content interaction. Make sure you have tracked a content impression using the same content name and
    557      * content piece, otherwise it will not count. To do so you should call the method do_track_content_impression();
    558      *
    559      * @param string      $interaction The name of the interaction with the content. For instance a 'click'.
    560      * @param string      $content_name The name of the content. For instance 'Ad Foo Bar'.
    561      * @param string      $content_piece The actual content. For instance the path to an image, video, audio, any text.
    562      * @param string|bool $content_target (optional) The target the content leading to when an interaction occurs. For instance the URL of a landing page.
    563      * @return mixed Response string or true if using bulk requests.
    564      */
    565     public function do_track_content_interaction(
    566         $interaction,
    567         $content_name,
    568         $content_piece = 'Unknown',
    569         $content_target = false
    570     ) {
    571         try {
    572             $url = $this->get_url_track_content_interaction( $interaction, $content_name, $content_piece, $content_target );
    573         } catch ( Exception $e ) {
    574             $e->getMessage();
    575         }
    576 
    577         return $this->send_request( $url );
    578     }
    579     /**
    580      * Tracks an internal Site Search query, and optionally tracks the Search Category, and Search results Count.
    581      * These are used to populate reports in Actions > Site Search.
    582      *
    583      * @param string   $keyword Searched query on the site.
    584      * @param string   $category (optional) Search engine category if applicable.
    585      * @param bool|int $count_results (optional) results displayed on the search result page. Used to track "zero result" keywords.
    586      *
    587      * @return mixed Response or true if using bulk requests.
    588      */
    589     public function do_track_site_search( $keyword, $category = '', $count_results = false ) {
    590         $url = $this->get_url_track_site_search( $keyword, $category, $count_results );
    591         return $this->send_request( $url );
    592     }
    593     /**
    594      * Records a Goal conversion
    595      *
    596      * @param int   $id_goal Id Goal to record a conversion.
    597      * @param float $revenue Revenue for this conversion.
    598      * @return mixed Response or true if using bulk request
    599      */
    600     public function do_track_goal( $id_goal, $revenue = 0.0 ) {
    601         $url = $this->get_url_track_goal( $id_goal, $revenue );
    602         return $this->send_request( $url );
    603     }
    604     /**
    605      * Tracks a download or outlink
    606      *
    607      * @param string $action_url URL of the download or outlink.
    608      * @param string $action_type Type of the action: 'download' or 'link'.
    609      * @return mixed Response or true if using bulk request
    610      */
    611     public function do_track_action( $action_url, $action_type ) {
    612         // Referrer could be udpated to be the current URL temporarily (to mimic JS behavior).
    613         $url = $this->get_url_track_action( $action_url, $action_type );
    614         return $this->send_request( $url );
    615     }
    616     /**
    617      * Adds an item in the Ecommerce order.
    618      *
    619      * This should be called before do_track_ecommerce_order(), or before do_track_ecommerce_cart_update().
    620      * This function can be called for all individual products in the cart (or order).
    621      * SKU parameter is mandatory. Other parameters are optional (set to false if value not known).
    622      * Ecommerce items added via this function are automatically cleared when do_track_ecommerce_order() or get_url_track_ecommerce_order() is called.
    623      *
    624      * @param string       $sku (required) SKU, Product identifier.
    625      * @param string       $name (optional) Product name.
    626      * @param string|array $category (optional) Product category, or array of product categories (up to 5 categories can be specified for a given product).
    627      * @param float|int    $price (optional) Individual product price (supports integer and decimal prices).
    628      * @param int          $quantity (optional) Product quantity. If not specified, will default to 1 in the Reports.
    629      * @throws Exception You must specify a SKU for the Ecommerce item.
    630      */
    631     public function add_ecommerce_item( $sku, $name = '', $category = '', $price = 0.0, $quantity = 1 ) {
    632         if ( empty( $sku ) ) {
    633             Humcommerce_logger::log( 'You must specify a SKU for the Ecommerce item' );
    634             return;
    635         }
    636         $price                   = $this->force_dot_as_separator_for_decimal_point( $price );
    637         $this->ecommerce_items[] = array( $sku, $name, $category, $price, $quantity );
    638     }
    639     /**
    640      * Tracks a Cart Update (add item, remove item, update item).
    641      *
    642      * On every Cart update, you must call add_ecommerce_item() for each item (product) in the cart,
    643      * including the items that haven't been updated since the last cart update.
    644      * Items which were in the previous cart and are not sent in later Cart updates will be deleted from the cart (in the database).
    645      *
    646      * @param float $grand_total Cart grand_total (typically the sum of all items' prices).
    647      * @return mixed Response or true if using bulk request
    648      */
    649     public function do_track_ecommerce_cart_update( $grand_total ) {
    650         $url = $this->get_url_track_ecommerce_cart_update( $grand_total );
    651         return $this->send_request( $url );
    652     }
    653     /**
    654      * Sends all stored tracking actions at once. Only has an effect if bulk tracking is enabled.
    655      *
    656      * To enable bulk tracking, call enable_bulk_tracking().
    657      *
    658      * @throws Exception Error:  you must call the function do_track_page_view or do_track_goal from this class,
    659     before calling this method do_bulk_track().
    660      * @return string Response|null
    661      */
    662     public function do_bulk_track() {
    663         if ( empty( $this->stored_tracking_actions ) ) {
    664             Humcommerce_logger::log(
    665                 'Error:  you must call the function do_track_page_view or do_track_goal from this class,
    666                  before calling this method do_bulk_track()'
    667             );
    668             return null;
    669         }
    670         $data = array( 'requests' => $this->stored_tracking_actions );
    671         // token_auth is not required by default, except if bulk_requests_require_authentication=1.
    672         if ( ! empty( $this->token_auth ) ) {
    673             $data['token_auth'] = $this->token_auth;
    674         }
    675         $post_data                     = wp_json_encode( $data );
    676         $response                      = $this->send_request( $this->get_base_url(), 'POST', $post_data, $force = true );
    677         $this->stored_tracking_actions = array();
    678         return $response;
    679     }
    680     /**
    681      * Tracks an Ecommerce order.
    682      *
    683      * If the Ecommerce order contains items (products), you must call first the add_ecommerce_item() for each item in the order.
    684      * All revenues (grand_total, sub_total, tax, shipping, discount) will be individually summed and reported in Humdash reports.
    685      * Only the parameters $order_id and $grand_total are required.
    686      *
    687      * @param string|int $order_id (required) Unique Order ID.
    688      *                This will be used to count this order only once in the event the order page is reloaded several times.
    689      *                order_id must be unique for each transaction, even on different days, or the transaction will not be recorded by Humdash.
    690      * @param float      $grand_total (required) Grand Total revenue of the transaction (including tax, shipping, etc.).
    691      * @param float      $sub_total (optional) Sub total amount, typically the sum of items prices for all items in this order (before Tax and Shipping costs are applied).
    692      * @param float      $tax (optional) Tax amount for this order.
    693      * @param float      $shipping (optional) Shipping amount for this order.
    694      * @param float      $discount (optional) Discounted amount in this order.
    695      * @return mixed Response or true if using bulk request
    696      */
    697     public function do_track_ecommerce_order(
    698         $order_id,
    699         $grand_total,
    700         $sub_total = 0.0,
    701         $tax = 0.0,
    702         $shipping = 0.0,
    703         $discount = 0.0
    704     ) {
    705         try {
    706             $url = $this->get_url_track_ecommerce_order( $order_id, $grand_total, $sub_total, $tax, $shipping, $discount );
    707         } catch ( Exception $e ) {
    708             $e->getMessage();
    709         }
    710 
    711         return $this->send_request( $url );
    712     }
    713     /**
    714      * Sends a ping request.
    715      *
    716      * Ping requests do not track new actions. If they are sent within the standard visit length (see global.ini.php),
    717      * they will extend the existing visit and the current last action for the visit. If after the standard visit length,
    718      * ping requests will create a new visit using the last action in the last known visit.
    719      *
    720      * @return mixed Response or true if using bulk request
    721      */
    722     public function do_ping() {
    723         $url  = $this->get_request( $this->idsite );
    724         $url .= '&ping=1';
    725         return $this->send_request( $url );
    726     }
    727     /**
    728      * Sets the current page view as an item (product) page view, or an Ecommerce Category page view.
    729      *
    730      * This must be called before do_track_page_view() on this product/category page.
    731      * It will set 3 custom variables of scope "page" with the SKU, Name and Category for this page view.
    732      * Note: Custom Variables of scope "page" slots 3, 4 and 5 will be used.
    733      *
    734      * On a category page, you may set the parameter $category only and set the other parameters to false.
    735      *
    736      * Tracking Product/Category page views will allow Humdash to report on Product & Categories
    737      * conversion rates (Conversion rate = Ecommerce orders containing this product or category / Visits to the product or category)
    738      *
    739      * @param string       $sku Product SKU being viewed.
    740      * @param string       $name Product Name being viewed.
    741      * @param string|array $category Category being viewed. On a Product page, this is the product's category.
    742      *                                You can also specify an array of up to 5 categories for a given page view.
    743      * @param float        $price Specify the price at which the item was displayed.
    744      * @return $this
    745      */
    746     public function set_ecommerce_view( $sku = '', $name = '', $category = '', $price = 0.0 ) {
    747         if ( ! empty( $category ) ) {
    748             if ( is_array( $category ) ) {
    749                 $category = wp_json_encode( $category );
    750             }
    751         } else {
    752             $category = '';
    753         }
    754         $this->page_custom_var[ self::CVAR_INDEX_ECOMMERCE_ITEM_CATEGORY ] = array( '_hac', $category );
    755         if ( ! empty( $price ) ) {
    756             $price = (float) $price;
    757             $price = $this->force_dot_as_separator_for_decimal_point( $price );
    758             $this->page_custom_var[ self::CVAR_INDEX_ECOMMERCE_ITEM_PRICE ] = array( '_hap', $price );
    759         }
    760         // On a category page, do not record "Product name not defined".
    761         if ( empty( $sku ) && empty( $name ) ) {
    762             return $this;
    763         }
    764         if ( ! empty( $sku ) ) {
    765             $this->page_custom_var[ self::CVAR_INDEX_ECOMMERCE_ITEM_SKU ] = array( '_has', $sku );
    766         }
    767         if ( empty( $name ) ) {
    768             $name = '';
    769         }
    770         $this->page_custom_var[ self::CVAR_INDEX_ECOMMERCE_ITEM_NAME ] = array( '_han', $name );
    771         return $this;
    772     }
    773     /**
    774      * Force the separator for decimal point to be a dot. See https://github.com/humdash/humdash/issues/6435
    775      * If for instance a German locale is used it would be a comma otherwise.
    776      *
    777      * @param  float|string $value value.
    778      * @return string
    779      */
    780     private function force_dot_as_separator_for_decimal_point( $value ) {
    781         if ( null === $value || false === $value ) {
    782             return $value;
    783         }
    784         return str_replace( ',', '.', $value );
    785     }
    786     /**
    787      * Returns URL used to track Ecommerce Cart updates
    788      * Calling this function will reinitializes the property ecommerce_items to empty array
    789      * so items will have to be added again via add_ecommerce_item()
    790      *
    791      * @param int $grand_total Grand total.
    792      *
    793      * @ignore
    794      */
    795     public function get_url_track_ecommerce_cart_update( $grand_total ) {
    796         try {
    797             $url = $this->get_url_track_ecommerce( $grand_total );
    798         } catch ( Exception $e ) {
    799             $e->getMessage();
    800         }
    801 
    802         return $url;
    803     }
    804 
    805     /**
    806      * Returns URL used to track Ecommerce Orders
    807      * Calling this function will reinitializes the property ecommerce_items to empty array
    808      * so items will have to be added again via add_ecommerce_item()
    809      *
    810      * @param int   $order_id Order Id.
    811      * @param int   $grand_total Grand total.
    812      * @param float $sub_total Sub total.
    813      * @param float $tax Tax.
    814      * @param float $shipping Shipping total.
    815      * @param float $discount Discount.
    816      *
    817      * @ignore
    818      * @throws Exception You must specifiy an order_id for the Ecommerce order.
    819      */
    820     public function get_url_track_ecommerce_order(
    821         $order_id,
    822         $grand_total,
    823         $sub_total = 0.0,
    824         $tax = 0.0,
    825         $shipping = 0.0,
    826         $discount = 0.0
    827     ) {
    828         if ( empty( $order_id ) ) {
    829             Humcommerce_logger::log( 'You must specifiy an order_id for the Ecommerce order' );
    830             return null;
    831         }
    832         try {
    833             $url = $this->get_url_track_ecommerce( $grand_total, $sub_total, $tax, $shipping, $discount );
    834         } catch ( Exception $e ) {
    835             $e->getMessage();
    836         }
    837         $url                                 .= '&ec_id=' . rawurlencode( $order_id );
    838         $this->ecommerce_last_order_timestamp = $this->get_timestamp();
    839         return $url;
    840     }
    841 
    842     /**
    843      * Returns URL used to track Ecommerce orders
    844      *
    845      * Calling this function will reinitializes the property ecommerce_items to empty array
    846      * so items will have to be added again via add_ecommerce_item()
    847      *
    848      * @param int   $grand_total Grand total.
    849      * @param float $sub_total Sub total.
    850      * @param float $tax Tax.
    851      * @param float $shipping Shipping total.
    852      * @param float $discount Discount.
    853      *
    854      * @ignore
    855      * @throws Exception You must specifiy a grand_total for the Ecommerce order (or Cart update).
    856      */
    857     protected function get_url_track_ecommerce( $grand_total, $sub_total = 0.0, $tax = 0.0, $shipping = 0.0, $discount = 0.0 ) {
    858         if ( ! is_numeric( $grand_total ) ) {
    859             Humcommerce_logger::log( 'You must specifiy a grand_total for the Ecommerce order (or Cart update)' );
    860             return null;
    861         }
    862         $url  = $this->get_request( $this->idsite );
    863         $url .= '&idgoal=0';
    864         if ( ! empty( $grand_total ) ) {
    865             $grand_total = $this->force_dot_as_separator_for_decimal_point( $grand_total );
    866             $url        .= '&revenue=' . $grand_total;
    867         }
    868         if ( ! empty( $sub_total ) ) {
    869             $sub_total = $this->force_dot_as_separator_for_decimal_point( $sub_total );
    870             $url      .= '&ec_st=' . $sub_total;
    871         }
    872         if ( ! empty( $tax ) ) {
    873             $tax  = $this->force_dot_as_separator_for_decimal_point( $tax );
    874             $url .= '&ec_tx=' . $tax;
    875         }
    876         if ( ! empty( $shipping ) ) {
    877             $shipping = $this->force_dot_as_separator_for_decimal_point( $shipping );
    878             $url     .= '&ec_sh=' . $shipping;
    879         }
    880         if ( ! empty( $discount ) ) {
    881             $discount = $this->force_dot_as_separator_for_decimal_point( $discount );
    882             $url     .= '&ec_dt=' . $discount;
    883         }
    884         if ( ! empty( $this->ecommerce_items ) ) {
    885             $url .= '&ec_items=' . rawurlencode( wp_json_encode( $this->ecommerce_items ) );
    886         }
    887 
    888         $this->ecommerce_items = array();
    889         return $url;
    890     }
    891     /**
    892      * Builds URL to track a page view.
    893      *
    894      * @see do_track_page_view()
    895      * @param string $document_title Page view name as it will appear in Humdash reports.
    896      * @return string URL to humdash.php with all parameters set to track the pageview
    897      */
    898     public function get_url_track_page_view( $document_title = '' ) {
    899         $url = $this->get_request( $this->idsite );
    900         if ( strlen( $document_title ) > 0 ) {
    901             $url .= '&action_name=' . rawurlencode( $document_title );
    902         }
    903         return $url;
    904     }
    905     /**
    906      * Builds URL to track a custom event.
    907      *
    908      * @see do_track_event()
    909      * @param string      $category The Event Category (Videos, Music, Games...).
    910      * @param string      $action The Event's Action (Play, Pause, Duration, Add Playlist, Downloaded, Clicked...).
    911      * @param string|bool $name (optional) The Event's object Name (a particular Movie name, or Song name, or File name...).
    912      * @param float|bool  $value (optional) The Event's value.
    913      * @return string URL to humdash.php with all parameters set to track the pageview|null
    914      * @throws Exception You must specify an Event Category name AND Event action.
    915      */
    916     public function get_url_track_event( $category, $action, $name = false, $value = false ) {
    917         $url = $this->get_request( $this->idsite );
    918         if ( strlen( $category ) === 0 ) {
    919             Humcommerce_logger::log( 'You must specify an Event Category name (Music, Videos, Games...).' );
    920             return null;
    921         }
    922         if ( strlen( $action ) === 0 ) {
    923             Humcommerce_logger::log( 'You must specify an Event action (click, view, add...).' );
    924             return null;
    925         }
    926         $url .= '&e_c=' . rawurlencode( $category );
    927         $url .= '&e_a=' . rawurlencode( $action );
    928         if ( strlen( $name ) > 0 ) {
    929             $url .= '&e_n=' . rawurlencode( $name );
    930         }
    931         if ( strlen( $value ) > 0 ) {
    932             $value = $this->force_dot_as_separator_for_decimal_point( $value );
    933             $url  .= '&e_v=' . $value;
    934         }
    935         return $url;
    936     }
    937     /**
    938      * Builds URL to track a content impression.
    939      *
    940      * @see do_track_content_impression()
    941      * @param string       $content_name The name of the content. For instance 'Ad Foo Bar'.
    942      * @param string       $content_piece The actual content. For instance the path to an image, video, audio, any text.
    943      * @param string|false $content_target (optional) The target of the content. For instance the URL of a landing page.
    944      * @throws Exception In case $content_name is empty|null.
    945      * @return string URL to humdash.php with all parameters set to track the pageview
    946      */
    947     public function get_url_track_content_impression( $content_name, $content_piece, $content_target ) {
    948         $url = $this->get_request( $this->idsite );
    949         if ( strlen( $content_name ) === 0 ) {
    950             Humcommerce_logger::log( 'You must specify a content name' );
    951             return null;
    952         }
    953         $url .= '&c_n=' . rawurlencode( $content_name );
    954         if ( ! empty( $content_piece ) && strlen( $content_piece ) > 0 ) {
    955             $url .= '&c_p=' . rawurlencode( $content_piece );
    956         }
    957         if ( ! empty( $content_target ) && strlen( $content_target ) > 0 ) {
    958             $url .= '&c_t=' . rawurlencode( $content_target );
    959         }
    960         return $url;
    961     }
    962     /**
    963      * Builds URL to track a content impression.
    964      *
    965      * @see do_track_content_interaction()
    966      * @param string       $interaction The name of the interaction with the content. For instance a 'click'.
    967      * @param string       $content_name The name of the content. For instance 'Ad Foo Bar'.
    968      * @param string       $content_piece The actual content. For instance the path to an image, video, audio, any text.
    969      * @param string|false $content_target (optional) The target the content leading to when an interaction occurs. For instance the URL of a landing page.
    970      * @throws Exception In case $interaction or $content_name is empty|null.
    971      * @return string URL to humdash.php with all parameters set to track the pageview
    972      */
    973     public function get_url_track_content_interaction( $interaction, $content_name, $content_piece, $content_target ) {
    974         $url = $this->get_request( $this->idsite );
    975         if ( strlen( $interaction ) === 0 ) {
    976             Humcommerce_logger::log( 'You must specify a name for the interaction' );
    977             return null;
    978         }
    979         if ( strlen( $content_name ) === 0 ) {
    980             Humcommerce_logger::log( 'You must specify a content name' );
    981             return null;
    982         }
    983         $url .= '&c_i=' . rawurlencode( $interaction );
    984         $url .= '&c_n=' . rawurlencode( $content_name );
    985         if ( ! empty( $content_piece ) && strlen( $content_piece ) > 0 ) {
    986             $url .= '&c_p=' . rawurlencode( $content_piece );
    987         }
    988         if ( ! empty( $content_target ) && strlen( $content_target ) > 0 ) {
    989             $url .= '&c_t=' . rawurlencode( $content_target );
    990         }
    991         return $url;
    992     }
    993     /**
    994      * Builds URL to track a site search.
    995      *
    996      * @see do_track_site_search()
    997      * @param string $keyword Keyword.
    998      * @param string $category Category.
    999      * @param int    $count_results Count Results.
    1000      * @return string
    1001      */
    1002     public function get_url_track_site_search( $keyword, $category, $count_results ) {
    1003         $url  = $this->get_request( $this->idsite );
    1004         $url .= '&search=' . rawurlencode( $keyword );
    1005         if ( strlen( $category ) > 0 ) {
    1006             $url .= '&search_cat=' . rawurlencode( $category );
    1007         }
    1008         if ( ! empty( $count_results ) || 0 === $count_results ) {
    1009             $url .= '&search_count=' . (int) $count_results;
    1010         }
    1011         return $url;
    1012     }
    1013     /**
    1014      * Builds URL to track a goal with id_goal and revenue.
    1015      *
    1016      * @see do_track_goal()
    1017      * @param int   $id_goal Id Goal to record a conversion.
    1018      * @param float $revenue Revenue for this conversion.
    1019      * @return string URL to humdash.php with all parameters set to track the goal conversion
    1020      */
    1021     public function get_url_track_goal( $id_goal, $revenue = 0.0 ) {
    1022         $url  = $this->get_request( $this->idsite );
    1023         $url .= '&idgoal=' . $id_goal;
    1024         if ( ! empty( $revenue ) ) {
    1025             $revenue = $this->force_dot_as_separator_for_decimal_point( $revenue );
    1026             $url    .= '&revenue=' . $revenue;
    1027         }
    1028         return $url;
    1029     }
    1030     /**
    1031      * Builds URL to track a new action.
    1032      *
    1033      * @see do_track_action()
    1034      * @param string $action_url URL of the download or outlink.
    1035      * @param string $action_type Type of the action: 'download' or 'link'.
    1036      * @return string URL to humdash.php with all parameters set to track an action
    1037      */
    1038     public function get_url_track_action( $action_url, $action_type ) {
    1039         $url  = $this->get_request( $this->idsite );
    1040         $url .= '&' . $action_type . '=' . rawurlencode( $action_url );
    1041         return $url;
    1042     }
    1043     /**
    1044      * Overrides server date and time for the tracking requests.
    1045      * By default Humdash will track requests for the "current datetime" but this function allows you
    1046      * to track visits in the past. All times are in UTC.
    1047      *
    1048      * Allowed only for Admin/Super User, must be used along with set_token_auth()
    1049      *
    1050      * @see set_token_auth()
    1051      * @param string $date_time Date with the format 'Y-m-d H:i:s', or a UNIX timestamp.
    1052      *               If the datetime is older than one day (default value for tracking_requests_require_authentication_when_custom_timestamp_newer_than), then you must call set_token_auth() with a valid Admin/Super user token.
    1053      * @return $this
    1054      */
    1055     public function set_force_visit_date_time( $date_time ) {
    1056         $this->forced_datetime = $date_time;
    1057         return $this;
    1058     }
    1059     /**
    1060      * Forces Humdash to create a new visit for the tracking request.
    1061      *
    1062      * By default, Humdash will create a new visit if the last request by this user was more than 30 minutes ago.
    1063      * If you call set_force_new_visit() before calling doTrack*, then a new visit will be created for this request.
    1064      *
    1065      * @return $this
    1066      */
    1067     public function set_force_new_visit() {
    1068         $this->forced_new_visit = true;
    1069         return $this;
    1070     }
    1071     /**
    1072      * Overrides IP address
    1073      *
    1074      * Allowed only for Admin/Super User, must be used along with set_token_auth()
    1075      *
    1076      * @see set_token_auth()
    1077      * @param string $ip IP string, eg. 130.54.2.1.
    1078      * @return $this
    1079      */
    1080     public function set_ip( $ip ) {
    1081         $this->ip = $ip;
    1082         return $this;
    1083     }
    1084     /**
    1085      * Force the action to be recorded for a specific User. The User ID is a string representing a given user in your system.
    1086      *
    1087      * A User ID can be a username, UUID or an email address, or any number or string that uniquely identifies a user or client.
    1088      *
    1089      * @param string $user_id Any user ID string (eg. email address, ID, username). Must be non empty. Set to false to de-assign a user id previously set.
    1090      * @return $this|null
    1091      * @throws Exception User ID cannot be empty.
    1092      */
    1093     public function set_user_id( $user_id ) {
    1094         if ( false === $user_id ) {
    1095             $this->set_new_visitor_id();
    1096             return $this;
    1097         }
    1098         if ( '' === $user_id ) {
    1099             Humcommerce_logger::log( 'User ID cannot be empty.' );
    1100             return null;
    1101         }
    1102         $this->user_id = $user_id;
    1103         return $this;
    1104     }
    1105     /**
    1106      * Hash function used internally by Humdash to hash a User ID into the Visitor ID.
    1107      *
    1108      * Note: matches implementation of Tracker\Request->get_user_id_hashed()
    1109      *
    1110      * @param int $id ID to hashed.
    1111      * @return string
    1112      */
    1113     public static function get_user_id_hashed( $id ) {
    1114         return substr( sha1( $id ), 0, 16 );
    1115     }
    1116     /**
    1117      * Forces the requests to be recorded for the specified Visitor ID.
    1118      * Note: it is recommended to use ->set_user_id($user_id); instead.
    1119      *
    1120      * Rather than letting Humdash attribute the user with a heuristic based on IP and other user fingeprinting attributes,
    1121      * force the action to be recorded for a particular visitor.
    1122      *
    1123      * If you use both set_visitor_id and set_user_id, set_user_id will take precedence.
    1124      * If not set, the visitor ID will be fetched from the 1st party cookie, or will be set to a random UUID.
    1125      *
    1126      * @deprecated We recommend to use  ->set_user_id($user_id).
    1127      * @param string $visitor_id 16 hexadecimal characters visitor ID, eg. "33c31e01394bdc63".
    1128      * @return $this|null
    1129      * @throws Exception It expects a hexadecimal characters.
    1130      */
    1131     public function set_visitor_id( $visitor_id ) {
    1132         $hex_chars = '01234567890abcdefABCDEF';
    1133         if ( strlen( $visitor_id ) !== self::LENGTH_VISITOR_ID
    1134             || strspn( $visitor_id, $hex_chars ) !== strlen( $visitor_id )
    1135         ) {
    1136             Humcommerce_logger::log(
    1137                 'set_visitor_id() expects a '
    1138                 . self::LENGTH_VISITOR_ID
    1139                 . ' characters hexadecimal string (containing only the following: '
    1140                 . $hex_chars
    1141                 . ')'
    1142             );
    1143             return null;
    1144         }
    1145         $this->forced_visitor_id = $visitor_id;
    1146         return $this;
    1147     }
    1148     /**
    1149      * If the user initiating the request has the Humdash first party cookie,
    1150      * this function will try and return the ID parsed from this first party cookie (found in $_COOKIE).
    1151      *
    1152      * If you call this function from a server, where the call is triggered by a cron or script
    1153      * not initiated by the actual visitor being tracked, then it will return
    1154      * the random Visitor ID that was assigned to this visit object.
    1155      *
    1156      * This can be used if you wish to record more visits, actions or goals for this visitor ID later on.
    1157      *
    1158      * @return string 16 hex chars visitor ID string
    1159      */
    1160     public function get_visitor_id() {
    1161         if ( ! empty( $this->user_id ) ) {
    1162             return $this->get_user_id_hashed( $this->user_id );
    1163         }
    1164         if ( ! empty( $this->forced_visitor_id ) ) {
    1165             return $this->forced_visitor_id;
    1166         }
    1167         if ( $this->load_visitor_id_cookie() ) {
    1168             return $this->cookie_visitor_id;
    1169         }
    1170         return $this->random_visitor_id;
    1171     }
    1172     /**
    1173      * Returns the currently set user agent.
    1174      *
    1175      * @return string
    1176      */
    1177     public function get_user_agent() {
    1178         return $this->user_agent;
    1179     }
    1180     /**
    1181      * Returns the currently set IP address.
    1182      *
    1183      * @return string
    1184      */
    1185     public function get_ip() {
    1186         return $this->ip;
    1187     }
    1188     /**
    1189      * Returns the User ID string, which may have been set via:
    1190      *     $v->set_user_id('username@example.org');
    1191      *
    1192      * @return bool
    1193      */
    1194     public function get_user_id() {
    1195         return $this->user_id;
    1196     }
    1197     /**
    1198      * Loads values from the VisitorId Cookie
    1199      *
    1200      * @return bool True if cookie exists and is valid, False otherwise
    1201      */
    1202     protected function load_visitor_id_cookie() {
    1203         $id_cookie = $this->get_cookie_matching_name( 'id' );
    1204         if ( false === $id_cookie ) {
    1205             return false;
    1206         }
    1207         $parts = explode( '.', $id_cookie );
    1208         if ( strlen( $parts[0] ) !== self::LENGTH_VISITOR_ID ) {
    1209             return false;
    1210         }
    1211 
    1212         /*
    1213         $this->cookie_visitor_id provides backward compatibility since get_visitor_id()
    1214         didn't change any existing VisitorId value
    1215         */
    1216         $this->cookie_visitor_id = $parts[0];
    1217         $this->create_ts         = $parts[1];
    1218         $this->visit_count       = (int) $parts[2];
    1219         $this->current_visit_ts  = $parts[3];
    1220         $this->last_visit_ts     = $parts[4];
    1221         if ( isset( $parts[5] ) ) {
    1222             $this->ecommerce_last_order_timestamp = $parts[5];
    1223         }
    1224         return true;
    1225     }
    1226     /**
    1227      * Deletes all first party cookies from the client
    1228      */
    1229     public function delete_cookies() {
    1230         $cookies = array( 'id', 'ses', 'cvar', 'ref' );
    1231         foreach ( $cookies as $cookie ) {
    1232             $this->set_cookie( $cookie, '', -86400 );
    1233         }
    1234     }
    1235     /**
    1236      * Returns the currently assigned Attribution Information stored in a first party cookie.
    1237      *
    1238      * This function will only work if the user is initiating the current request, and his cookies
    1239      * can be read by PHP from the $_COOKIE array.
    1240      *
    1241      * @return string JSON Encoded string containing the Referrer information for Goal conversion attribution.
    1242      *                Will return false if the cookie could not be found
    1243      * @see Humdash.js get_attribution_info()
    1244      */
    1245     public function get_attribution_info() {
    1246         if ( ! empty( $this->attribution_info ) ) {
    1247             return wp_json_encode( $this->attribution_info );
    1248         }
    1249         return $this->get_cookie_matching_name( 'ref' );
    1250     }
    1251     /**
    1252      * Some Tracking API functionality requires express authentication, using either the
    1253      * Super User token_auth, or a user with 'admin' access to the website.
    1254      *
    1255      * The following features require access:
    1256      * - force the visitor IP
    1257      * - force the date &  time of the tracking requests rather than track for the current datetime
    1258      *
    1259      * @param string $token_auth token_auth 32 chars token_auth string.
    1260      * @return $this
    1261      */
    1262     public function set_token_auth( $token_auth ) {
    1263         $this->token_auth = $token_auth;
    1264         return $this;
    1265     }
    1266     /**
    1267      * Sets local visitor time
    1268      *
    1269      * @param string $time HH:MM:SS format.
    1270      * @return $this
    1271      */
    1272     public function set_local_time( $time ) {
    1273         list($hour, $minute, $second) = explode( ':', $time );
    1274         $this->local_hour             = (int) $hour;
    1275         $this->local_minute           = (int) $minute;
    1276         $this->local_second           = (int) $second;
    1277         return $this;
    1278     }
    1279     /**
    1280      * Sets user resolution width and height.
    1281      *
    1282      * @param int $width Width.
    1283      * @param int $height Height.
    1284      * @return $this
    1285      */
    1286     public function set_resolution( $width, $height ) {
    1287         $this->width  = $width;
    1288         $this->height = $height;
    1289         return $this;
    1290     }
    1291     /**
    1292      * Sets if the browser supports cookies
    1293      * This is reported in "List of plugins" report in Humdash.
    1294      *
    1295      * @param bool $bool True/False.
    1296      * @return $this
    1297      */
    1298     public function set_browser_has_cookies( $bool ) {
    1299         $this->has_cookies = $bool;
    1300         return $this;
    1301     }
    1302     /**
    1303      * Will append a custom string at the end of the Tracking request.
    1304      *
    1305      * @param string $string String to append.
    1306      * @return $this
    1307      */
    1308     public function set_debug_string_append( $string ) {
    1309         $this->debug_append_url = '&' . $string;
    1310         return $this;
    1311     }
    1312     /**
    1313      * Sets visitor browser supported plugins
    1314      *
    1315      * @param bool $flash Flash.
    1316      * @param bool $java Java.
    1317      * @param bool $director Director.
    1318      * @param bool $quick_time Quick Time.
    1319      * @param bool $real_player Real Player.
    1320      * @param bool $pdf PDF.
    1321      * @param bool $windows_media Windows Media.
    1322      * @param bool $gears Gears.
    1323      * @param bool $silverlight Silverlight.
    1324      * @return $this
    1325      */
    1326     public function set_plugins(
    1327         $flash = false,
    1328         $java = false,
    1329         $director = false,
    1330         $quick_time = false,
    1331         $real_player = false,
    1332         $pdf = false,
    1333         $windows_media = false,
    1334         $gears = false,
    1335         $silverlight = false
    1336     ) {
    1337         $this->plugins =
    1338             '&fla=' . (int) $flash .
    1339             '&java=' . (int) $java .
    1340             '&dir=' . (int) $director .
    1341             '&qt=' . (int) $quick_time .
    1342             '&realp=' . (int) $real_player .
    1343             '&pdf=' . (int) $pdf .
    1344             '&wma=' . (int) $windows_media .
    1345             '&gears=' . (int) $gears .
    1346             '&ag=' . (int) $silverlight;
    1347         return $this;
    1348     }
    1349     /**
    1350      * By default, HumdashTracker will read first party cookies
    1351      * from the request and write updated cookies in the response (using setrawcookie).
    1352      * This can be disabled by calling this function.
    1353      */
    1354     public function disable_cookie_support() {
    1355         $this->config_cookies_disabled = true;
    1356     }
    1357     /**
    1358      * Returns the maximum number of seconds the tracker will spend waiting for a response
    1359      * from Humdash. Defaults to 600 seconds.
    1360      */
    1361     public function get_request_timeout() {
    1362         return $this->request_timeout;
    1363     }
    1364     /**
    1365      * Sets the maximum number of seconds that the tracker will spend waiting for a response
    1366      * from Humdash.
    1367      *
    1368      * @param int $timeout Time to wait.
    1369      * @return $this|null
    1370      * @throws Exception Invalid value supplied for request timeout.
    1371      */
    1372     public function set_request_timeout( $timeout ) {
    1373         if ( ! is_int( $timeout ) || $timeout < 0 ) {
    1374             Humcommerce_logger::log( "Invalid value supplied for request timeout: $timeout" );
    1375             return null;
    1376         }
    1377         $this->request_timeout = $timeout;
    1378         return $this;
    1379     }
    1380     /**
    1381      * If a proxy is needed to look up the address of the Humdash site, set it with this
    1382      *
    1383      * @param string $proxy IP as string, for example "173.234.92.107".
    1384      * @param int    $proxy_port Proxy Port.
    1385      */
    1386     public function set_proxy( $proxy, $proxy_port = 80 ) {
    1387         $this->proxy      = $proxy;
    1388         $this->proxy_port = $proxy_port;
    1389     }
    1390     /**
    1391      * If the proxy IP and the proxy port have been set, with the set_proxy() function
    1392      * returns a string, like "173.234.92.107:80"
    1393      */
    1394     private function get_proxy() {
    1395         if ( isset( $this->proxy ) && isset( $this->proxy_port ) ) {
    1396             return $this->proxy . ':' . $this->proxy_port;
    1397         }
    1398         return null;
    1399     }
    1400     /**
    1401      * Used in tests to output useful error messages.
    1402      *
    1403      * @var string
    1404      * @ignore
    1405      */
    1406     public static $debug_last_requested_url = false;
    1407     /**
    1408      * Sends the request to HumDash
    1409      *
    1410      * @param string $url Humdash Url.
    1411      * @param string $method HTTP Method.
    1412      * @param string $data Data to be tracked.
    1413      * @param bool   $force Force.
    1414      *
    1415      * @ignore
    1416      */
    1417     protected function send_request( $url, $method = 'GET', $data = null, $force = false ) {
    1418         self::$debug_last_requested_url = $url;
    1419         // if doing a bulk request, store the url.
    1420         if ( $this->do_bulk_requests && ! $force ) {
    1421             $this->stored_tracking_actions[]
    1422                 = $url
    1423                 . ( ! empty( $this->user_agent ) ? ( '&ua=' . rawurlencode( $this->user_agent ) ) : '' )
    1424                 . ( ! empty( $this->accept_language ) ? ( '&lang=' . rawurlencode( $this->accept_language ) ) : '' );
    1425             // Clear custom variables so they don't get copied over to other users in the bulk request.
    1426             $this->clear_custom_variables();
    1427             $this->clear_custom_tracking_parameters();
    1428             $this->user_agent      = false;
    1429             $this->accept_language = false;
    1430             return true;
    1431         }
    1432         $proxy = $this->get_proxy();
    1433         if ( function_exists( 'curl_init' ) && function_exists( 'curl_exec' ) ) {
    1434             $options = array(
    1435                 CURLOPT_URL            => $url,
    1436                 CURLOPT_USERAGENT      => $this->user_agent,
    1437                 CURLOPT_HEADER         => true,
    1438                 CURLOPT_TIMEOUT        => $this->request_timeout,
    1439                 CURLOPT_RETURNTRANSFER => true,
    1440                 CURLOPT_HTTPHEADER     => array(
    1441                     'Accept-Language: ' . $this->accept_language,
    1442                 ),
    1443             );
    1444             if ( defined( 'PATH_TO_CERTIFICATES_FILE' ) ) {
    1445                 $options[ CURLOPT_CAINFO ] = PATH_TO_CERTIFICATES_FILE;
    1446             }
    1447             if ( isset( $proxy ) ) {
    1448                 $options[ CURLOPT_PROXY ] = $proxy;
    1449             }
    1450             switch ( $method ) {
    1451                 case 'POST':
    1452                     $options[ CURLOPT_POST ] = true;
    1453                     break;
    1454                 default:
    1455                     break;
    1456             }
    1457             // only supports JSON data.
    1458             if ( ! empty( $data ) ) {
    1459                 $options[ CURLOPT_HTTPHEADER ][] = 'Content-Type: application/json';
    1460                 $options[ CURLOPT_HTTPHEADER ][] = 'Expect:';
    1461                 $options[ CURLOPT_POSTFIELDS ]   = $data;
    1462             }
    1463             if ( ! empty( $this->outgoing_tracker_cookies ) ) {
    1464                 $options[ CURLOPT_COOKIE ]      = http_build_query( $this->outgoing_tracker_cookies );
    1465                 $this->outgoing_tracker_cookies = array();
    1466             }
    1467 
    1468             $ch = curl_init(); // phpcs:ignore
    1469             curl_setopt_array( $ch, $options ); // phpcs:ignore
    1470             ob_start();
    1471             $response = @curl_exec( $ch ); // phpcs:ignore
    1472             ob_end_clean();
    1473             $header  = '';
    1474             $content = '';
    1475             if ( ! empty( $response ) ) {
    1476                 list($header, $content) = explode( "\r\n\r\n", $response, $limit_count = 2 );
    1477             }
    1478 
    1479             $this->parse_incoming_cookies( explode( "\r\n", $header ) );
    1480         } elseif ( function_exists( 'stream_context_create' ) ) {
    1481             $stream_options = array(
    1482                 'http' => array(
    1483                     'method'     => $method,
    1484                     'user_agent' => $this->user_agent,
    1485                     'header'     => 'Accept-Language: ' . $this->accept_language . "\r\n",
    1486                     'timeout'    => $this->request_timeout, // PHP 5.2.1.
    1487                 ),
    1488             );
    1489             if ( isset( $proxy ) ) {
    1490                 $stream_options['http']['proxy'] = $proxy;
    1491             }
    1492             // only supports JSON data.
    1493             if ( ! empty( $data ) ) {
    1494                 $stream_options['http']['header'] .= "Content-Type: application/json \r\n";
    1495                 $stream_options['http']['content'] = $data;
    1496             }
    1497             if ( ! empty( $this->outgoing_tracker_cookies ) ) {
    1498                 $stream_options['http']['header'] .= 'Cookie: ' . http_build_query( $this->outgoing_tracker_cookies ) . "\r\n";
    1499                 $this->outgoing_tracker_cookies    = array();
    1500             }
    1501 
    1502             $ctx      = stream_context_create( $stream_options );
    1503             $response = wp_remote_get( $url, $ctx );
    1504             $content  = $response;
    1505 
    1506             $this->parse_incoming_cookies( $http_response_header );
    1507         }
    1508         return $content;
    1509     }
    1510     /**
    1511      * Returns current timestamp, or forced timestamp/datetime if it was set
    1512      *
    1513      * @return string|int
    1514      */
    1515     protected function get_timestamp() {
    1516         return ! empty( $this->forced_datetime )
    1517             ? strtotime( $this->forced_datetime )
    1518             : time();
    1519     }
    1520 
    1521     /**
    1522      * Returns the base URL for the humdash server.
    1523      *
    1524      * @throws Exception If Humdash URL is not provided.
    1525      */
    1526     protected function get_base_url() {
    1527         if ( empty( self::$url ) ) {
    1528             Humcommerce_logger::log(
    1529                 'You must first set the Humdash Tracker URL by calling
    1530                  HumdashTracker::$url = \'http://your-website.org/humdash/\';'
    1531             );
    1532             return null;
    1533         }
    1534         if ( strpos( self::$url, '/humdash.php' ) === false
    1535             && strpos( self::$url, '/proxy-humdash.php' ) === false
    1536         ) {
    1537             self::$url .= '/humdash.php';
    1538         }
    1539         return self::$url;
    1540     }
    1541     /**
    1542      *
    1543      * Returns the request url.
    1544      *
    1545      * @param int $idsite Id of Site.
    1546      *
    1547      * @ignore
    1548      */
    1549     protected function get_request( $idsite ) {
    1550         $this->set_first_party_cookies();
    1551         $custom_fields = '';
    1552         if ( ! empty( $this->custom_parameters ) ) {
    1553             $custom_fields = '&' . http_build_query( $this->custom_parameters, '', '&' );
    1554         }
    1555         try {
    1556             $url = $this->get_base_url() .
    1557                 '?idsite=' . $idsite .
    1558                 '&rec=1' .
    1559                 '&apiv=' . self::VERSION .
    1560                 '&r=' . substr( strval( wp_rand() ), 2, 6 ) .
    1561                 // Only allowed for Admin/Super User, token_auth required.
    1562                 ( ! empty( $this->ip ) ? '&cip=' . $this->ip : '' ) .
    1563                 ( ! empty( $this->user_id ) ? '&uid=' . rawurlencode( $this->user_id ) : '' ) .
    1564                 ( ! empty( $this->forced_datetime ) ? '&cdt=' . rawurlencode( $this->forced_datetime ) : '' ) .
    1565                 ( ! empty( $this->forced_new_visit ) ? '&new_visit=1' : '' ) .
    1566                 ( ( ! empty( $this->token_auth ) && ! $this->do_bulk_requests ) ?
    1567                     '&token_auth=' . rawurlencode( $this->token_auth ) : '' ) .
    1568                 // Values collected from cookie.
    1569                 '&_idts=' . $this->create_ts .
    1570                 '&_idvc=' . $this->visit_count .
    1571                 ( ! empty( $this->last_visit_ts ) ? '&_viewts=' . $this->last_visit_ts : '' ) .
    1572                 ( ! empty( $this->ecommerce_last_order_timestamp ) ?
    1573                     '&_ects=' . rawurlencode( $this->ecommerce_last_order_timestamp ) : '' ) .
    1574                 // These parameters are set by the JS, but optional when using API.
    1575                 ( ! empty( $this->plugins ) ? $this->plugins : '' ) .
    1576                 ( ( false !== $this->local_hour && false !== $this->local_minute && false !== $this->local_second ) ?
    1577                     '&h=' . $this->local_hour . '&m=' . $this->local_minute . '&s=' . $this->local_second : '' ) .
    1578                 ( ! empty( $this->width ) && ! empty( $this->height ) ? '&res=' . $this->width . 'x' . $this->height : '' ) .
    1579                 ( ! empty( $this->has_cookies ) ? '&cookie=' . $this->has_cookies : '' ) .
    1580                 // Various important attributes.
    1581                 ( ! empty( $this->custom_data ) ? '&data=' . $this->custom_data : '' ) .
    1582                 ( ! empty( $this->visitor_custom_var ) ? '&_cvar=' . rawurlencode( wp_json_encode( $this->visitor_custom_var ) ) : '' ) .
    1583                 ( ! empty( $this->page_custom_var ) ? '&cvar=' . rawurlencode( wp_json_encode( $this->page_custom_var ) ) : '' ) .
    1584                 ( ! empty( $this->event_custom_var ) ? '&e_cvar=' . rawurlencode( wp_json_encode( $this->event_custom_var ) ) : '' ) .
    1585                 ( ! empty( $this->generation_time ) ? '&gt_ms=' . ( (int) $this->generation_time ) : '' ) .
    1586                 ( ! empty( $this->forced_visitor_id ) ? '&cid=' . $this->forced_visitor_id : '&_id=' . $this->get_visitor_id() ) .
    1587                 // URL parameters.
    1588                 '&url=' . rawurlencode( $this->page_url ) .
    1589                 '&urlref=' . rawurlencode( $this->url_referrer ) .
    1590                 ( ( ! empty( $this->page_charset ) && $this->page_charset !== self::DEFAULT_CHARSET_PARAMETER_VALUES ) ? // phpcs:ignore
    1591                     '&cs=' . $this->page_charset : '' ) .
    1592                 // unique pageview id.
    1593                 ( ! empty( $this->id_pageview ) ? '&pv_id=' . rawurlencode( $this->id_pageview ) : '' ) .
    1594                 // Attribution information, so that Goal conversions are attributed to the right referrer or campaign.
    1595                 // Campaign name.
    1596                 ( ! empty( $this->attribution_info[0] ) ? '&_rcn=' . rawurlencode( $this->attribution_info[0] ) : '' ) .
    1597                 // Campaign keyword.
    1598                 ( ! empty( $this->attribution_info[1] ) ? '&_rck=' . rawurlencode( $this->attribution_info[1] ) : '' ) .
    1599                 // Timestamp at which the referrer was set.
    1600                 ( ! empty( $this->attribution_info[2] ) ? '&_refts=' . $this->attribution_info[2] : '' ) .
    1601                 // Referrer URL.
    1602                 ( ! empty( $this->attribution_info[3] ) ? '&_ref=' . rawurlencode( $this->attribution_info[3] ) : '' ) .
    1603                 // custom location info.
    1604                 ( ! empty( $this->country ) ? '&country=' . rawurlencode( $this->country ) : '' ) .
    1605                 ( ! empty( $this->region ) ? '&region=' . rawurlencode( $this->region ) : '' ) .
    1606                 ( ! empty( $this->city ) ? '&city=' . rawurlencode( $this->city ) : '' ) .
    1607                 ( ! empty( $this->lat ) ? '&lat=' . rawurlencode( $this->lat ) : '' ) .
    1608                 ( ! empty( $this->long ) ? '&long=' . rawurlencode( $this->long ) : '' ) .
    1609                 $custom_fields .
    1610                 ( ! $this->send_image_response ? '&send_image=0' : '' ) .
    1611                 // DEBUG.
    1612                 $this->debug_append_url;
    1613         } catch ( Exception $e ) {
    1614             $e->getMessage();
    1615         }
    1616         // Reset page level custom variables after this page view.
    1617         $this->page_custom_var  = array();
    1618         $this->event_custom_var = array();
    1619         $this->clear_custom_tracking_parameters();
    1620         // force new visit only once, user must call again set_force_new_visit().
    1621         $this->forced_new_visit = false;
    1622         return $url;
    1623     }
     394
    1624395    /**
    1625396     * Returns a first party cookie which name contains $name
     
    1729500            . self::get_current_query_string();
    1730501    }
    1731     /**
    1732      * Sets the first party cookies as would the humdash.js
    1733      * All cookies are supported: 'id' and 'ses' and 'ref' and 'cvar' cookies.
    1734      *
    1735      * @return $this
    1736      */
    1737     protected function set_first_party_cookies() {
    1738         if ( $this->config_cookies_disabled ) {
    1739             return $this;
    1740         }
    1741         if ( empty( $this->cookie_visitor_id ) ) {
    1742             $this->load_visitor_id_cookie();
    1743         }
    1744         // Set the 'ref' cookie.
    1745         $attribution_info = $this->get_attribution_info();
    1746         if ( ! empty( $attribution_info ) ) {
    1747             $this->set_cookie( 'ref', $attribution_info, $this->config_referral_cookie_timeout );
    1748         }
    1749         // Set the 'ses' cookie.
    1750         $this->set_cookie( 'ses', '*', $this->config_session_cookie_timeout );
    1751         // Set the 'id' cookie.
    1752         $visit_count  = $this->visit_count + 1;
    1753         $cookie_value = $this->get_visitor_id() . '.' . $this->create_ts . '.' . $visit_count . '.' . $this->current_ts .
    1754             '.' . $this->last_visit_ts . '.' . $this->ecommerce_last_order_timestamp;
    1755         $this->set_cookie( 'id', $cookie_value, $this->config_visitor_cookie_timeout );
    1756         // Set the 'cvar' cookie.
    1757         $this->set_cookie( 'cvar', wp_json_encode( $this->visitor_custom_var ), $this->config_session_cookie_timeout );
    1758         return $this;
    1759     }
    1760     /**
    1761      * Sets a first party cookie to the client to improve dual JS-PHP tracking.
    1762      *
    1763      * This replicates the humdash.js tracker algorithms for consistency and better accuracy.
    1764      *
    1765      * @param string $cookie_name Name.
    1766      * @param string $cookie_value Value.
    1767      * @param string $cookie_ttl Ttl.
    1768      * @return $this
    1769      */
    1770     protected function set_cookie( $cookie_name, $cookie_value, $cookie_ttl ) {
    1771         $cookie_expire = $this->current_ts + $cookie_ttl;
    1772         if ( ! headers_sent() ) {
    1773             setcookie(
    1774                 $this->get_cookie_name( $cookie_name ),
    1775                 $cookie_value,
    1776                 $cookie_expire,
    1777                 $this->config_cookie_path,
    1778                 $this->config_cookie_domain
    1779             );
    1780         }
    1781         return $this;
    1782     }
     502
    1783503    /**
    1784504     * Gets custom variables from cookie.
     
    1793513        return json_decode( $cookie, $assoc = true );
    1794514    }
    1795     /**
    1796      * Sets a cookie to be sent to the tracking server.
    1797      *
    1798      * @param string $name Name.
    1799      * @param string $value Value.
    1800      */
    1801     public function set_outgoing_tracker_cookie( $name, $value ) {
    1802         if ( null === $value ) {
    1803             unset( $this->outgoing_tracker_cookies[ $name ] );
    1804         } else {
    1805             $this->outgoing_tracker_cookies[ $name ] = $value;
    1806         }
    1807     }
    1808 
    1809     /**
    1810      * Gets a cookie which was set by the tracking server.
    1811      *
    1812      * @param string $name Name.
    1813      *
    1814      * @return bool|string
    1815      */
    1816     public function get_incoming_tracker_cookie( $name ) {
    1817         if ( isset( $this->incoming_tracker_cookies[ $name ] ) ) {
    1818             return $this->incoming_tracker_cookies[ $name ];
    1819         }
    1820 
    1821         return false;
    1822     }
    1823     /**
    1824      * Reads incoming tracking server cookies.
    1825      *
    1826      * @param array $headers Array with HTTP response headers as values.
    1827      */
    1828     protected function parse_incoming_cookies( $headers ) {
    1829         $this->incoming_tracker_cookies = array();
    1830 
    1831         if ( ! empty( $headers ) ) {
    1832             $header_name        = 'set-cookie:';
    1833             $header_name_length = strlen( $header_name );
    1834 
    1835             foreach ( $headers as $header ) {
    1836                 if ( strpos( strtolower( $header ), $header_name ) !== 0 ) {
    1837                     continue;
    1838                 }
    1839                 $cookies = trim( substr( $header, $header_name_length ) );
    1840                 $pos_end = strpos( $cookies, ';' );
    1841                 if ( false !== $pos_end ) {
    1842                     $cookies = substr( $cookies, 0, $pos_end );
    1843                 }
    1844                 parse_str( $cookies, $this->incoming_tracker_cookies );
    1845             }
    1846         }
    1847     }
    1848 
    1849     /**
    1850      * Helper function to quickly generate the URL to track a page view.
    1851      *
    1852      * @param int    $idsite Id of Site.
    1853      * @param string $document_title Title of Page or document.
    1854      * @return string
    1855      */
    1856     protected function humdash_get_url_track_page_view( $idsite, $document_title = '' ) {
    1857         $tracker = new HumdashTracker( $idsite );
    1858         return $tracker->get_url_track_page_view( $document_title );
    1859     }
    1860     /**
    1861      * Helper function to quickly generate the URL to track a goal.
    1862      *
    1863      * @param int   $idsite Id of site.
    1864      * @param int   $id_goal Goal Id.
    1865      * @param float $revenue Revenue.
    1866      * @return string
    1867      */
    1868     protected function humdash_get_url_track_goal( $idsite, $id_goal, $revenue = 0.0 ) {
    1869         $tracker = new HumdashTracker( $idsite );
    1870         return $tracker->get_url_track_goal( $id_goal, $revenue );
    1871     }
     515
    1872516}
  • humcommerce/trunk/public/class-humcommerce-public.php

    r2217514 r2270638  
    172172                    _ha.push(["setSiteId", "' . esc_js( $options['si'] ) . '"]);
    173173                    var d=document, g=d.createElement("script"), s=d.getElementsByTagName("script")[0];
    174                     g.type="text/javascript"; g.async=true; g.defer=true; g.src=u+"humdash.js"; s.parentNode.insertBefore(g,s);
     174                    g.type="text/javascript"; g.async=true; g.defer=true; g.src=u+"sites/h-' . esc_js( $options['si'] ) . '.js"; s.parentNode.insertBefore(g,s);
    175175                  })();
    176176                </script>
    177177           <!-- End HumDash Code -->';  // phpcs:ignore
    178178        }
    179     }
    180 
    181     /**
    182      * To update tracking code for updated cart.
    183      *
    184      * @since    1.0.0
    185      */
    186     public function track_update_cart() {
    187         global $woocommerce;
    188         $items = $woocommerce->cart->get_cart();
    189         $total = 0;
    190         foreach ( $items as $item => $values ) {
    191             $_product       = wc_get_product( $values['data']->get_id() );
    192             $category_terms = get_the_terms( $values['data']->get_id(), 'product_cat' );
    193             $category_array = $this->get_categories_array( $category_terms );
    194             $product_sku    = $_product->get_sku();
    195             if ( empty( $product_sku ) ) {
    196                 $product_name = $_product->get_title();
    197                 $product_id   = $_product->get_id();
    198                 $product_sku  = $product_name . $product_id;
    199             }
    200             $this->tracker->add_ecommerce_item( $product_sku, $_product->get_title(), $category_array, $_product->get_price(), $values['quantity'] );
    201             $total = $total + $_product->get_price() * $values['quantity'];
    202         }
    203 
    204         $cart = $woocommerce->cart;
    205         if ( ! empty( $cart->total ) ) {
    206             if ( empty( $cart->applied_coupons ) ) {
    207                 $total = $total + $cart->get_shipping_total();
    208             } else {
    209                 $total = $total - $cart->get_discount_total() + $cart->get_shipping_total();
    210             }
    211         } elseif ( ! empty( $cart->cart_contents_total ) ) {
    212             $total = $cart->cart_contents_total;
    213         }
    214         $this->tracker->do_track_ecommerce_cart_update( $total );
    215     }
    216 
    217     /**
    218      * To update tracking code for updated cart.
    219      *
    220      * @since    1.0.0
    221      * @param string $cart_updated Flag for cart updated.
    222      */
    223     public function track_update_cart_updated( $cart_updated ) {
    224         $this->track_update_cart();
    225         return $cart_updated;
    226     }
    227 
    228     /**
    229      * To track ecommerce order.
    230      *
    231      * @since    1.0.0
    232      * @param int $order_id Order id.
    233      */
    234     public function track_ecommerce_order( $order_id ) {
    235 
    236         if ( get_post_meta( $order_id, '_tracked', 1 ) === 1 ) {
    237             return;
    238         }
    239 
    240         $code  = '';
    241         $order = wc_get_order( $order_id );
    242 
    243         foreach ( $order->get_items() as $item_key => $item_values ) {
    244             $product = $item_values->get_product();
    245 
    246             $item_data = $item_values->get_data();
    247 
    248             $product_name   = $item_data['name'];
    249             $product_id     = $item_data['product_id'];
    250             $category_terms = get_the_terms( $product_id, 'product_cat' );
    251             $category_array = $this->get_categories_array( $category_terms );
    252             $quantity       = $item_data['quantity'];
    253             $product_sku    = $product->get_sku();
    254             $product_price  = $product->get_price();
    255             if ( empty( $product_sku ) ) {
    256                 $product_sku = $product_name . $product_id;
    257             }
    258             $this->tracker->add_ecommerce_item( $product_sku, $product_name, $category_array, $product_price, $quantity );
    259         }
    260 
    261         $shipping_amt = $this->woocommerce_version3() ? $order->get_shipping_total() : $order->get_total_shipping();
    262         $this->tracker->do_track_ecommerce_order( $order_id, $order->get_total(), $order->get_subtotal(), $order->get_cart_tax(), $shipping_amt, $order->get_total_discount() );
    263         update_post_meta( $order_id, '_tracked', 1 );
    264     }
    265 
    266     /**
    267      * Compare the currently installed version of WooCommerce.
    268      *
    269      * @since    1.0.0
    270      */
    271     public function woocommerce_version3() {
    272         global $woocommerce;
    273         $result = version_compare( $woocommerce->version, '3.0', '>=' );
    274         return $result;
    275     }
    276 
    277     /**
    278      * To get Categories array.
    279      *
    280      * @since    1.0.0
    281      * @param array $category_terms Category Terms.
    282      */
    283     public function get_categories_array( $category_terms ) {
    284         $categories = array();
    285         if ( is_wp_error( $category_terms ) ) {
    286             return $categories;
    287         }
    288         if ( ! empty( $category_terms ) ) {
    289             foreach ( $category_terms as $category ) {
    290                 $categories[] = $category->name;
    291             }
    292         }
    293         $categories     = array_unique( $categories );
    294         $categories     = array_slice( $categories, 0, 5 );
    295         $category_array = '';
    296         foreach ( $categories as $category ) {
    297             $category_array .= '"' . $category . '",';
    298         }
    299         return $category_array;
    300179    }
    301180
Note: See TracChangeset for help on using the changeset viewer.