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
WooCommerce Hooks: https://woocommerce.com/document/introduction-to-hooks-actions-and-filters/
What You’ll Need From R!
Get these values from your Retention.com Implementation Manager - they are used in the code below.
Your R! Script Identifier (a seven character code)
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
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 classNamesThese 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.