Changeset 2270638
- Timestamp:
- 03/30/2020 10:02:06 AM (6 years ago)
- Location:
- humcommerce/trunk
- Files:
-
- 5 edited
-
README.txt (modified) (1 diff)
-
humcommerce-functions.php (modified) (3 diffs)
-
includes/class-humcommerce.php (modified) (1 diff)
-
libs/class-humdashtracker.php (modified) (4 diffs)
-
public/class-humcommerce-public.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
humcommerce/trunk/README.txt
r2262445 r2270638 145 145 == Changelog == 146 146 147 Ver 2.1.14 (27 Mar 2020) 148 * Fix : Removed e-commerce integration. 149 147 150 Ver 2.1.13 (24 Dec 2019) 148 151 * Feature : Added a functionality to install the plugin automatically in OnBoarding process of HumCommerce Application. -
humcommerce/trunk/humcommerce-functions.php
r2022506 r2270638 5 5 } 6 6 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 }42 7 43 8 add_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');51 9 52 10 function add_humcommerce_script_to_wp_head() … … 59 17 _ha.push(['enableLinkTracking']); 60 18 (function() { 61 var u=\"//app.hum dash.com/\";19 var u=\"//app.humcommerce.com/\"; 62 20 _ha.push(['setTrackerUrl', u+'humdash.php']); 63 21 _ha.push(['setSiteId', '" . $options["si"] . "']); 64 22 })(); 65 23 </script> 66 <script type=\"text/javascript\" src=\"//app.hum dash.com/humdash.js\"></script>24 <script type=\"text/javascript\" src=\"//app.humcommerce.com/humdash.js\"></script> 67 25 <!-- End HumDash Code -->"; 68 26 delete_option('humcommerce_add_to_cart'); … … 72 30 } 73 31 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 141 141 142 142 $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' );150 143 } 151 144 -
humcommerce/trunk/libs/class-humdashtracker.php
r2217514 r2270638 374 374 return $this; 375 375 } 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 485 377 /** 486 378 * Get cookie name with prefix and domain hash … … 500 392 return self::FIRST_PARTY_COOKIES_PREFIX . $cookie_name . '.' . $this->idsite . '.' . $hash; 501 393 } 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 ) ? '>_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 ) ? '®ion=' . 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 1624 395 /** 1625 396 * Returns a first party cookie which name contains $name … … 1729 500 . self::get_current_query_string(); 1730 501 } 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 1783 503 /** 1784 504 * Gets custom variables from cookie. … … 1793 513 return json_decode( $cookie, $assoc = true ); 1794 514 } 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 1872 516 } -
humcommerce/trunk/public/class-humcommerce-public.php
r2217514 r2270638 172 172 _ha.push(["setSiteId", "' . esc_js( $options['si'] ) . '"]); 173 173 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); 175 175 })(); 176 176 </script> 177 177 <!-- End HumDash Code -->'; // phpcs:ignore 178 178 } 179 }180 181 /**182 * To update tracking code for updated cart.183 *184 * @since 1.0.0185 */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.0221 * @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.0232 * @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.0270 */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.0281 * @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;300 179 } 301 180
Note: See TracChangeset
for help on using the changeset viewer.