All Collections
Integrations
Other Integrations
WooCommerce Installation Guide
WooCommerce Installation Guide
Updated over a week ago

This guide outlines the procedure for integrating Retention.com scripts into a WooCommerce setup within WordPress. The integration facilitates capturing identity, specific user interactions, and order details within the platform.

The R! code snippet includes several functions:

  • Net New lead Collection ("Grow")

  • Add to Cart events

  • Viewed Product Events

  • Revenue (order) Tracking

We’ve provided guidance on adding the full script with all functions (recommended) as well as breakdowns for how each function is created in the event you want to make your own edits.

Relevant Documentation


What You’ll Need From R!

Get these values from your Retention.com Implementation Manager - they are used in the code below.

  1. Your R! Script Identifier (a seven character code)

  2. The script version (SNIPPET_VERSION)

*Please note that the value shown in the screenshot is just a placeholder, you will need to get your unique identifier from your Implementation Manager.


Creating a Code Snippet in WordPress

Retention.com’s Script is is added as a Snippet in WordPress Admin view as follows:

Steps 1: Go to Snippets and click on "Add New"

Step 2: Name the snippet Retention & Select PHP as the style for the snippet

Step 3: Copy the code below into your new snippet

Retention Code Snippet (Complete Version) - please expand

Copying all of the code in this section into WooCommerce will result in enabling all of Retention’s script functionality. However, your scripts will not go live until your Implementation Manager signs off on your implementation phase.


Please keep an eye out for the following comment in the code:

//Get this from your dedicated Implementation Manager

You are required to update the respective values in order for the script to work correctly.

NOTE: Once the script has been installed and tested on your website, we advise removing any console.log commands.

Code

function geq_script_function() {
echo "<script type='text/javascript'>
!function(){
var geq = window.geq = window.geq || [];
if (geq.initialize || geq.invoked) {
if (window.console) console.error('GE snippet included twice.');
return;
}
var retention_account_id = '**GET FROM Implementation Manager**';
geq.invoked = true;
var methods = ['page', 'suppress', 'trackOrder', 'identify', 'addToCart', 'callBack', 'event'];
for (var i = 0; i < methods.length; i++) {
var key = methods[i];
geq[key] = function(method){
return function(){
var args = Array.prototype.slice.call(arguments);
args.unshift(method);
geq.push(args);
return geq;
};
}(key);
}
geq.load = function(key){
var script = document.createElement('script');
script.type = 'text/javascript';
script.async = true;
script.src = 'https://s3-us-west-2.amazonaws.com/jsstore/a/' + key + '/ge.js' + (location.href.includes('vge=true') ? '?v=' + Math.random() : '');
var firstScript = document.getElementsByTagName('script')[0];
firstScript.parentNode.insertBefore(script, firstScript);
};
geq.SNIPPET_VERSION = '1.6.1';
geq.load(retention_account_id);
}();
</script>";
echo "<script>geq.page()</script>";
}
add_action('wp_head', 'geq_script_function');

function my_enqueue_scripts() {
wp_enqueue_script('my-ajax-handle', get_template_directory_uri() . '/js/myscript.js', array('jquery'), null, true);
wp_localize_script('my-ajax-handle', 'the_ajax_script', array('ajaxurl' => admin_url('admin-ajax.php')));
}
add_action('wp_enqueue_scripts', 'my_enqueue_scripts');

function geq_atc_button_listeners_function() {
echo '<script>if (window.location.href.includes("vge=true")) {
console.log("Triggered geq_atc_button_listeners_function");
}</script>';
$atcScriptListeners = "<script type='text/javascript'>
var atc_item = typeof vpitem !== 'undefined' ? vpitem : (typeof item !== 'undefined' ? item : {});
if (!atc_item.hasOwnProperty('Name')) {
if (atc_item.hasOwnProperty('Title')) {
atc_item.Name = atc_item.Title;
if (window.location.href.includes('vge=true')) {
console.log('The item uses Title property');
}
} else {
if (window.location.href.includes('vge=true')) {
console.error('The item does not have a Name or Title property. This may result in an issue.');
}
}
}
var classNames = ['single_add_to_cart_button', 'add_to_cart_button'];
classNames.forEach(function(className) {
var atcButtons = document.getElementsByClassName(className);
if (atcButtons && atcButtons.length > 0) {
for (var i = 0; i < atcButtons.length; i++) {
atcButtons[i].addEventListener('click', function() {
if (atc_item && Object.keys(atc_item).length > 0) {
console.log('Add To Cart Reclaim', atc_item);
geq.addToCart(atc_item);
} else {
if (window.location.href.includes('vge=true')) {
console.log('HAS NO item for Add To Cart Reclaim - Getting Last Cart Item');
}
var data = {'action': 'geq_atc_from_cart_action'};
$.post(the_ajax_script.ajaxurl, data, function(response) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.innerHTML = response;
document.body.appendChild(script);
});
}
});
}
} else {
if (window.location.href.includes('vge=true')) {
console.error('No Add To Cart buttons found for class ' + className);
}
}
});
</script>";
echo $atcScriptListeners;
}
add_action('wp_footer', 'geq_atc_button_listeners_function');

function viewed_product_reclaim() {
global $product;
echo '<script>if (window.location.href.includes("vge=true")) {
console.log("Triggered viewed_product_reclaim --> $product",'. json_encode($product) .');
}</script>';
if (isset($product) && is_object($product)) {
$product_id = $product->get_id();
$product_name = $product->get_name();
$product_brand = $product->get_attribute('brand');
$product_price = $product->get_price();
$product_image = wp_get_attachment_image_url($product->get_image_id(), 'full');
$product_categories = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'names'));
if (!empty($product_categories) && is_array($product_categories)) {
$first_category = $product_categories[0];
}
$vpScript = "<script type='text/javascript'>
if (window.location.href.includes('vge=true')) {
console.log('Viewed Product ID: {$product_id}');
}
var vpitem = {
Name: " . json_encode($product_name) . ",
Price: " . json_encode($product_price) . ",
ProductID: " . json_encode($product_id) . ",
Categories: " . json_encode($first_category) . ",
ImageURL: " . json_encode($product_image) . ",
URL: window.location.href,
Brand: " . json_encode($product_brand) . "
};
if (window.location.href.includes('vge=true')) {
console.log('Viewed Product Reclaim', vpitem);
}
if (typeof geq !== 'undefined' && typeof geq.event === 'function') {
geq.event('Viewed Product Reclaim', vpitem);
}
</script>";
echo $vpScript;
} else {
echo '<script>if (window.location.href.includes("vge=true")) {
console.log("Global product object is not set.");
}</script>';
}
}
add_action('woocommerce_after_single_product', 'viewed_product_reclaim');

function geq_atc_from_cart_function() {
$cart = WC()->cart->get_cart();
$cart_items = array_reverse($cart);
$latest_cart_item = reset($cart_items);
$latest_atc_product = isset($latest_cart_item['data']) ? $latest_cart_item['data'] : null;
if ($latest_atc_product && is_object($latest_atc_product)) {
$product_id = $latest_atc_product->get_id();
$product_name = $latest_atc_product->get_name();
$product_brand = $latest_atc_product->get_attribute('brand');
$product_price = $latest_atc_product->get_price();
$product_image = wp_get_attachment_image_url($latest_atc_product->get_image_id(), 'full');
$product_categories = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'names'));
$first_category = !empty($product_categories) && is_array($product_categories) ? $product_categories[0] : '';
$atcScript = "<script type='text/javascript'>
var atcitem = {
Name: " . json_encode($product_name) . ",
Price: " . json_encode($product_price) . ",
ProductID: " . json_encode($product_id) . ",
Categories: " . json_encode($first_category) . ",
ImageURL: " . json_encode($product_image) . ",
URL: window.location.href,
Brand: " . json_encode($product_brand) . "
};
if (window.location.href.includes('vge=true')) {
console.log('Add To Cart Item:', atcitem);
}
if (typeof geq !== 'undefined' && typeof geq.addToCart === 'function') {
geq.addToCart(atcitem);
}
</script>";
echo $atcScript;
}
wp_die();
}
add_action('wp_ajax_geq_atc_from_cart_action', 'geq_atc_from_cart_function');
add_action('wp_ajax_nopriv_geq_atc_from_cart_action', 'geq_atc_from_cart_function');

function geq_track_order_function($order_id) {
$georder = wc_get_order($order_id);
if (!($georder instanceof WC_Order)) {
return;
}
$order_details = [
'order_number' => $georder->get_order_number(),
'order_amount' => $georder->get_total(),
'order_email' => $georder->get_billing_email(),
];
if (in_array(null, $order_details, true)) {
return;
}
$order_json = json_encode($order_details);
echo "<script type='text/javascript'>
geq.trackOrder($order_json);
if (window.location.href.includes('vge=true')) {
console.log('Triggered geq_track_order_function with order ID: $order_id');
console.log('Called geq.trackOrder:', $order_json);
}
</script>";
}
add_action('woocommerce_thankyou', 'geq_track_order_function');

Step 4: Press Save & then Press Activate

You should see something like this on the Snippet page when complete.


Set up Reclaim: Viewed Product & Add to Cart

You can skip this implementation if you have already added the Complete Version to your site, outlined in the previous section.

Keep an eye out for the following in the code below:

//Get this from your dedicated Implementation Manager

Anything below with the comment above requires updates based on your specific set-up.

In this section we create a new function, geq_script_function, to house the script. This function needs to run on every page you want Retention.com’s services to operate.

This function is triggered by the hook, wp_head, which runs on every page and inserts the following code snippet into the header section:

function geq_script_function() {
    echo "<script type='text/javascript'>!function(){var geq=window.geq=window.geq||[];if(geq.initialize||geq.invoked){if(window.console)console.error('GE snippet included twice.');return;}
	
	//Get this from your dedicated Implementation Manager
	var retention_account_id ='FROM R!';
	
	geq.invoked=true;var methods=['page','suppress','trackOrder','identify','addToCart','callBack','event'];for(var i=0;i<methods.length;i++){var key=methods[i];geq[key]=function(method){return function(){var args=Array.prototype.slice.call(arguments);args.unshift(method);geq.push(args);return geq;};}(key);}geq.load=function(key){var script=document.createElement('script');script.type='text/javascript';script.async=true;script.src='https://s3-us-west-2.amazonaws.com/jsstore/a/'+key+'/ge.js'+(location.href.includes('vge=true')?'?v='+Math.random():'');var firstScript=document.getElementsByTagName('script')[0];firstScript.parentNode.insertBefore(script,firstScript);};
	
	//Get this from your EPIP Implementation Manager
	geq.SNIPPET_VERSION='1.6.1';
	
	geq.load(retention_account_id);}();</script>";
    
	echo "<script>geq.page()</script>";
}
add_action('wp_head', 'geq_script_function');
function my_enqueue_scripts() {
    wp_enqueue_script('my-ajax-handle', get_template_directory_uri().'/js/myscript.js', array('jquery'), null, true);
    wp_localize_script('my-ajax-handle', 'the_ajax_script', array('ajaxurl'=>admin_url('admin-ajax.php')));
}
add_action('wp_enqueue_scripts', 'my_enqueue_scripts');

This will not affect your website performance.


Viewed Product

  • Here, we create a new function, viewed_product_add_to_cart_reclaim. Inside this function, use the global $product object to retrieve the current product's details.

  • This function is triggered by the hook: woocommerce_after_single_product action. This action is triggered after the single product's details are displayed on the product page.

function viewed_product_reclaim() {    	
	
	global $product;
	echo '<script>if (window.location.href.includes("vge=true")) {console.log("Triggered viewed_product_reclaim --> $product",'. json_encode($product) .');}</script>';		  
    // Check if the global product object is set
    if (isset($product) && is_object($product)) {
        // Fetch product details
        $product_id = $product->get_id();
        $product_name = $product->get_name();
        $product_brand = $product->get_attribute('brand');  // Assuming 'brand' is your attribute for brands
        $product_price = $product->get_price();
        $product_image = wp_get_attachment_image_url($product->get_image_id(), 'full');
		$product_categories = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'names')); // Get product categories
		if (!empty($product_categories) && is_array($product_categories)) {
			$first_category = $product_categories[0]; // Get the first category
	}
        // Prepare the script with product details
        $vpScript = "<script type='text/javascript'>
       
	   if (window.location.href.includes('vge=true')) {
            console.log('Viewed Product ID: {$product_id}');
        }
            var vpitem = {
                Name: " . json_encode($product_name) . ",
				Price: " . json_encode($product_price) . ",
                ProductID: " . json_encode($product_id) . ",
                Categories: " . json_encode($first_category) . ",
                ImageURL: " . json_encode($product_image) . ",
                URL: window.location.href,
                Brand: " . json_encode($product_brand) . "              
            };
             if (window.location.href.includes('vge=true')) {
            	console.log('Viewed Product Reclaim', vpitem);
        		}
            // Trigger the event with the product data
            if (typeof geq !== 'undefined' && typeof geq.event === 'function') {
                geq.event('Viewed Product Reclaim', vpitem);
            }
        </script>";
        echo $vpScript;
    } else {
		echo '<script>if (window.location.href.includes("vge=true")) {console.log("Global product object is not set.");}</script>';		  
    }
}
add_action('woocommerce_after_single_product', 'viewed_product_reclaim');


Add to Cart

  • First, create 2 new functions, geq_atc_button_listeners_function & geq_atc_from_cart_function to house the new script.

  • Inside this function, geq_atc_button_listeners_function :

    • Add the HTML Classes for all of your add to cart buttons formatted as: 'button_class_name1', 'button_class_name2', etc. into the variable:
      var classNames

    • These class names MUST be the same class name your Add to Cart buttons use - Doing so will trigger our add to cart function when they are pressed

  • The geq_atc_from_cart_function is a backup function used to fetch the last product that was added to the cart in case the user adds a product to the cart outside of a single product page.

Note: For fetching the brand, we've assumed that there’s an attribute named 'brand'. If the brand information is stored differently, you would need to adjust the $product_brand = $product->get_attribute('brand'); line accordingly.

Note: we also include a secondary option for enabling add to cart if the hook is not working by using class listeners.

function geq_atc_button_listeners_function() {    
    echo '<script>if (window.location.href.includes("vge=true")) {console.log("Triggered geq_atc_button_listeners_function");}</script>';          
    // Script to handle ATC button event listeners
    $atcScriptListeners = "
    <script type='text/javascript'>
       
       var classNames = ['single_add_to_cart_button', 'add_to_cart_button'];
 // Check if 'vpitem' is defined; otherwise, try using 'item' or define a new one.
        var atc_item = typeof vpitem !== 'undefined' ? vpitem : (typeof item !== 'undefined' ? item : {});
        // Check if 'item' has a 'Name' property; if not, try to set it if 'Title' exists.
        if (!atc_item.hasOwnProperty('Name')) {
            if (atc_item.hasOwnProperty('Title')) { // Assuming 'Title' is the relevant property.
                atc_item.Name = atc_item.Title;
                if (window.location.href.includes('vge=true')) {console.log('The item uses Title property');}    
            } else {
                // Handle the case when neither 'Name' nor 'Title' property exists.
                if (window.location.href.includes('vge=true')) {console.error('The item does not have a Name or Title property. This may result in an issue.');}    
            }}
       
        classNames.forEach(function(className) {
            var atcButtons = document.getElementsByClassName(className);
            if (atcButtons && atcButtons.length > 0) {
                for (var i = 0; i < atcButtons.length; i++) {
                    atcButtons[i].addEventListener('click', function() {
                        if (atc_item && Object.keys(atc_item).length > 0) {
                            console.log('Add To Cart Reclaim', atc_item);
                            geq.addToCart(atc_item);
                        } else {
                            
							 if (window.location.href.includes('vge=true')) {console.log('HAS NO item for Add To Cart Reclaim - Getting Last Cart Item');}    
                            // Calling the PHP function via AJAX
                            var data = {'action': 'geq_atc_from_cart_action'};
                            // the_ajax_script.ajaxurl is a variable that will contain the URL to the ajax processing file in the WordPress backend.
                            //console.log('Calling the server');
                            $.post(the_ajax_script.ajaxurl, data, function(response) {
                                //console.log('Got this from the server: ' + response);
                                // Create a script tag and set its HTML to the response text
                                var script = document.createElement('script');
                                script.type = 'text/javascript';
                                script.innerHTML = response;  // Assuming 'response' is the JavaScript code you received
                                // Append the script to the DOM so it gets executed
                                document.body.appendChild(script);
                            });}});}
            } else {if (window.location.href.includes('vge=true')) {console.error('No Add To Cart buttons found for class ' + className);}}
        });
    </script>";
    echo $atcScriptListeners;        
}
add_action('wp_footer', 'geq_atc_button_listeners_function');
function geq_atc_from_cart_function() {
	
	//echo '<script>if (window.location.href.includes("vge=true")) {console.log("Triggered geq_atc_from_cart_function");}</script>';		  
	
    // Get the last item added to the cart
    $cart = WC()->cart->get_cart();
    $cart_items = array_reverse($cart);
    $latest_cart_item = reset($cart_items); // Gets the first item from the reversed array, which is the latest item added to cart
    $latest_atc_product = isset($latest_cart_item['data']) ? $latest_cart_item['data'] : null;
    // Check if the product object is set
    if ($latest_atc_product && is_object($latest_atc_product)) {
        // Fetch product details
        $product_id = $latest_atc_product->get_id();
        $product_name = $latest_atc_product->get_name();
        $product_brand = $latest_atc_product->get_attribute('brand');
        $product_price = $latest_atc_product->get_price();
        $product_image = wp_get_attachment_image_url($latest_atc_product->get_image_id(), 'full');
        $product_categories = wp_get_post_terms($product_id, 'product_cat', array('fields' => 'names'));
        $first_category = !empty($product_categories) && is_array($product_categories) ? $product_categories[0] : '';
        // Prepare the script with product details
        $atcScript = "var atcitem = {
                Name: " . json_encode($product_name) . ",
                Price: " . json_encode($product_price) . ",
                ProductID: " . json_encode($product_id) . ",
                Categories: " . json_encode($first_category) . ",
                ImageURL: " . json_encode($product_image) . ",
                URL: window.location.href,
                Brand: " . json_encode($product_brand) . "
            };
            
            if (window.location.href.includes('vge=true')) {
                console.log('Add To Cart Item:', atcitem);
            }
            // Trigger the addToCart event with the latest product data
            if (typeof geq !== 'undefined' && typeof geq.addToCart === 'function') {
                geq.addToCart(atcitem);
            }";
        echo $atcScript;
      } else {}
    wp_die();
 }
add_action('wp_ajax_geq_atc_from_cart_action', 'geq_atc_from_cart_function');
add_action('wp_ajax_nopriv_geq_atc_from_cart_action', 'geq_atc_from_cart_function');


Revenue Tracking

  • First, create a new function, geq_track_order_function, to house the new script.

  • Inside this function, use the $order_id to retrieve the order and get its corresponding details

  • This function is triggered by the hook: woocommerce_thankyou action. This action is triggered on the thank you page that displays after an order is placed.

function geq_track_order_function($order_id) {
    $georder = wc_get_order($order_id);
    // Check if the order object exists and is an instance of WC_Order
    if (!($georder instanceof WC_Order)) {
        return;
    }
    // Retrieve order details with error checking
    $order_details = [
        'order_number' => $georder->get_order_number(),
        'order_amount' => $georder->get_total(),
        'order_email'  => $georder->get_billing_email(),
    ];
    // Check for missing order details
    if (in_array(null, $order_details, true)) {
        return;
    }
    // Embed the JavaScript for order tracking
    $order_json = json_encode($order_details);
    echo "<script type='text/javascript'>
       geq.trackOrder($order_json);
      if (window.location.href.includes('vge=true')) {
            console.log('Triggered geq_track_order_function with order ID: $order_id');
            console.log('Called geq.trackOrder:', $order_json);           
        }
    </script>";
}
// Hook the function to run after an order is placed
add_action('woocommerce_thankyou', 'geq_track_order_function');


Disclaimer

These scripts attempt to utilize the hook capabilities offered by WooCommerce, and are intended to be lightweight and perform well in the majority of scenarios. We understand that every website is unique and as such, variations may be required by your team.

Did this answer your question?