Initialization of RoboTint
To initialize RoboTint, you need to include the following JavaScript into all pages inside the <body> tag:
<script src="https://core.robotint.net/s.js"></script>
<script>
	var aRobotintOptions={
	    tintSettings:{
	   	 CLIENT_ID:1234,
	   	 SECRET:"xxxxxxxx",
	   	 WITH_PRICE: 1
	    },
	    siteSettings:{
	   	colorSelect: funcСolorSelect,
		basketURL: "/personal/cart/"
	    }
	};
	obColorer.setOptions(aRobotintOptions);
</script>

tintSettings Array Description
array

CLIENT_ID
Client Identification number — Mandatory

SECRET
Secret code provided to the client — Mandatory

WITH_PRICE
Should always be set to 1

USE_SWITCHER
It is mandatory to use the selector of compatible tints in accordance with the base.
0 - do not display the switch, display only compatible tints
1 - show the switch in the "all shades" position, allow the user to switch back to displaying only compatible shades - the default


lang
Setting the language locale. Supported values:
en - English
es - Spanish
pt - Portuguese
More language packs will be added in the future
The variable name and the value must be in lowercase


siteSettings
nested array description

colorSelect
Callback function that returns the dataset on the tint selected by the user. Mandatory ifr the data on the tinting services is being added to the shopping cart

basketURL
The address of the shopping cart page of the online store, which is accessed by clicking the “Go to Cart” button within RoboTint’s UI. The default value is "/personal/cart/"

Example of data returned to the colorSelect function
{
    BASE_TYPE_INT: 1,
    BASKET_ID: 0,
    COLLECTION_ID: 131,
    COLLECTION_NAME: "Sample Collection Name",
    COLOR_ID: 65712,
    COLOR_NAME: "TVT F346",
    COLOR_PRICE: 120,
    PRICE_PER_LITER:40,
    PRICE_PER_CAN:120,
    HEX: "#e4e1ed",
    VOLUME: 3,
    VOLUME_UNIT: "l",
    COLLECTION_VENDOR_ID: 3,
    action: "add"
}

BASE_TYPE_INT
Product Base Type
1 — base А
3 — base C


BASKET_ID
This parameter is transmitted from the button's data-basket-id data attribute. Usually required in order to determine whether a new product or a product that is already in the customer's shopping cart is being tinted. Can be used to implement the tinting logics within the shopping cart

COLLECTION_ID
Color collection ID according to RoboTint’s database

COLLECTION_VENDOR_ID
Tinting system ID
Supported values:
3 - Tikkurila (Avatint)
5 - Akzo Nobel (Acomix)
6 - Ceresit
7 - Caparol Unitint
8 - Caparol Capotint 2.0
13 - Meffert
31 - Ebe
32 - Osnovit
This parameter indicates which tinting system was used for the calculations.


COLLECTION_NAME
The name of the color collection

COLOR_ID
The identifier of the tint selected by the user according to RoboTint’s database

COLOR_NAME
The tint code according to the manufacturers encoding, for example TVT F346

COLOR_PRICE
The tinting services price for the full volume of the can

PRICE_PER_LITER
The tinting services price per liter

PRICE_PER_CAN
Tinting price per full can of paint

HEX
RGB-code or the selected tint

VOLUME
The volume of the can in liters

VOLUME_UNIT
Unit of volume or weight

action
RoboTint’s technical value. Not used for integrations. Variable name is always in lowercase
The structure of the JSON array passed in the 'data-tint-data' attribute for the button
Attention: the name of the parameters must be indicated in capital letters. The parameters are case sensitive.
{
    "BARCODE":"xxxx",
    "PRODUCT_PRICE":370,
    "PRODUCT_ID":123,
    "VOLUME":3
}

Description of the parameters passed in the 'data-tint-data' attribute:

BARCODE
Product’s barcode. A mandatory parameter. Used for standard integration.

PRODUCT_ID
Product ID in the customer database - optional.
Used to process the returned result and display the selected color in the cart. Allows you to determine which product was tinted


PRODUCT_PRICE
Product price - optional

VOLUME
Volume of the can in liters. Optional for barcode integration — we know the volume ourselves, unless you’re dealing with a non-standard can size

Attention: if the VOLUME value that is passed in the array is different from the data contained in the RoboTint database, the specified values ​​will override the value of the packing volume for tinting calculation

Integration of RoboTint button into the webstore’s interface

The RoboTint button automatically checks if the product is available for tinting. To disable the button for products that are not supported by RoboTint, add the following CSS-rule:


tint-button[disabled]{display:none !important;}

Please note that the value of the data-tint-data attribute must be enclosed in single quotes for the data to be correctly interpreted.
Vertically-oriented button:
<tint-button disabled="disabled" data-basket-id='0' data-tint-button="1" data-tint-button-vertical="1" data-tint-data='JSON Array' onclick="obColorer.show(this)">
    <tint-span>choose</tint-span>
    <tint-span>color</tint-span>
</tint-button>
Horizontally-oriented button:
<tint-button disabled="disabled" data-tint-button="1" data-tint-button-horizontal="1" data-tint-data='JSON Array' data-basket-id="0" onclick="obColorer.show(this)">
    <tint-span>choose color</tint-span>
</tint-button>
RoboTint button integration in custom design

To add a call to the RoboTint component in any page element, you need to add the following attributes to the parent tag:


  • disabled="disabled" — recommended. If specified, the original element will be deactivated. The system automatically activates it on the onLoad() event. This activation happens only for the products that can be tinted.
  • data-tint-button="1" — mandatory. Specifies that RoboTint activation will be attached to this element.
  • data-tint-data='JSON Array' — data, passed into the call for tinting calculation
  • data-basket-id=’0’ — optional. Attribute with cart id.
  • onclick="obColorer.show(this)" — click-handling function
The process of processing the returned data on the side of the webstore:
Recommended Structure of the Result Handler Function

This function must be passed to obColorer using the setOption method (see example below), it occurs after the client clicks the “add to cart” / “color” button.
function selectRobotintColor(data) {
	var iProductID = parseInt(data.PRODUCT_ID); // getting the ID of the tinted product in the database of the online store

	var $itemObject = obColorer.itemObject;
	if (iProductID) { //if chosen product is allowed to be tinted
		var basketAction = "add"; //by default, consider that a new tinting service is being added to the basket

		var iBasketID = data.BASKET_ID; //get the value with the id of the item in the cart, if this value is passed


		if (iBasketID) { //if the ID of the item in the cart is passed

			basketAction = "update"; //it means that a tint has already been selected for this product. Set action to update the selected tint
 -- update
			obColorer.close(); //close RoboTint
		}

		data.basketAction = basketAction; //define the operation to be executed in the current object

		$.ajax({ //send the request
			type: "POST", // POST-method
			url: "/some/dir/path/ajax.php", //path to the script for adding/updating the color and product in the cart (depends on the CMS you use)

			data: data, //pass an object with all the dataset returned

			timeout: 15000, //wait for a response from the server within 15 seconds. After that -- stop waiting

			beforeSend: function () { //a function that can be used to execute custom logics while waiting for a response from the server. For example, showing a spinner

				...
			},
			success: function (data, textstatus) { //the result of the ajax request will be returned into this function

				...
			},
			error: function () { //
ajax request error handler function if something went wrong

				...
			}
		});
	}
}

Rounding examples and price levels
Most of our clients face two types of challenges when integrating RoboTint into their online stores.
  1. tinting services price rounding per liter
  2. setting a minimum price for the tinting services or price ranges
Both tasks can be solved in Javascript code on the client side by setting the appropriate options in obColorer.options.

The options.siteSettings.processPrice option is a function that will be called after the user selects a tint. In our framework, we pass the ProcessPrice method of the obRobotint object. An example of this object can be found below.


<script>
options.siteSettings = {
	bgZindex: 10000,
	colorSelect: obRobotint.select, // callback-function for transferring the item to the cart

	processPrice: obRobotint.processPrice // callback-function for processing the tinting price
};
obColorer.setOptions(options);	
 </script>
Price Processor function
In this function, you can carry out any manipulations with the price and volume of the product being tinted.

We have the following structure:

- prices array (contains all price config options that we want to define)
- processPrice method (manipulates the price in accordance with the config)
- numberFormat method (converts the price to the form we need)
- select method

You can use any config structure and price handler logic; in this case, we are only providing one example of implementation

var obRobotint = {

    prices:[], // this variable will contain all the settings for the price handler options configurators listed below
    processPrice: function($priceObj, data){ 
// this function will be passed to obColorer in order to process the prices before displaying them to the customer
 
// $priceObj  - price calculation data
// data - tints collection data

 	var data_raw = $priceObj.data();
	var ppl_raw = parseFloat(data_raw.pricePerLitr);
	var ppc_raw = parseFloat(data_raw.pricePerCan);
	var ppl = ppl_raw; // saving into a separate variable that will be processed
	var ppc = ppc_raw; // saving into a separate variable that will be processed
	var ref_vol = parseFloat(data_raw.priceRef_can_volume); // volume of tinted product according to 	the database
   	
	// volume of the tinted product
	var iVolume = ref_vol ;
		
	CVID = data.COLLECTION_VENDOR_ID 
	// stub if for some reason there is no Vendor ID

	if(!CVID) CVID = 2 // USE COLLECTION_VENDOR_ID from the vendor list

	// here we will store the selected config, but for now it is false
	var cur_set = false;

	// bypass the prices from the config in order to select the desired
      // in the corresponding price range and the corresponding syste
				
     for(var i in obRobotint.prices) {
		// configuration array of price levels and rounding
	
		rt_price = obRobotint.prices[i];
			if(rt_price['tint_system'] == CVID){
				// if the price falls within the range, then this section is selected within the pricing 					configurator
				if(ppl > rt_price.price_from ){
					cur_set = rt_price
				}
			}
		}		

		// if the config is not set, then set the default values
		if(!cur_set){
			 cur_set = {
				'price_from': 0,
				'tint_system': CVID , // here we have our chosen COLLECTION_VENDOR_ID
				'set_price': false,
				'round': false,
				'scale': false,	};
		}
 
			// update the price to the level
				if(cur_set.set_price){
 					ppl = cur_set.set_price;  // setting PricePerLiter 
				}
				
				// rounding 
				if(cur_set.round){
					// if precision of rounding is not specified then =1
					// scale possible values 1,10,100,1000
                         cur_set.scale  = parseInt(cur_set.scale);
	 				
					 // also processing the possible errors
					if(!cur_set.scale  || cur_set.scale  == 0){
						cur_set.scale = 1;
					}				
 
					// rounding types
					if(cur_set.round == 'math'){
 						ppl = Math.round(ppl/cur_set.scale)*cur_set.scale; 
					}else if(cur_set.round == 'up'){
 						ppl = Math.ceil(ppl/cur_set.scale)*cur_set.scale; 
					}else if(cur_set.round == 'down'){
 						ppl = Math.floor(ppl/cur_set.scale)*cur_set.scale; 
					}else{
 						ppl = Math.round(ppl/cur_set.scale)*cur_set.scale; 
					}
 				}

	 ppc = ppl*iVolume; // tinting price per can = price per liter * volume of the can
        if(ppc!=ppc_raw){
		// rewrite the value of the button to the calculated one, adjusted to the desired level
            $priceObj.attr("data-price-shop",price);
            $priceObj.text(obRobotint.numberFormat(ppc,0,"."," ")+" $");
        }
    },
	numberFormat: function ( number, decimals, dec_point, thousands_sep ) {	
// this function will format the price as we need
// Format a number with grouped thousands
    //
			// +   original by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
			// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
			// +	 bugfix by: Michael White (http://crestidg.com)
			var i, j, kw, kd, km;
	
			// input sanitation & defaults
			if( isNaN(decimals = Math.abs(decimals)) ){
					decimals = 2;
			}
			if( dec_point == undefined ){
					dec_point = ",";
			}
			if( thousands_sep == undefined ){
					thousands_sep = ".";
			}
	
			i = parseInt(number = (+number || 0).toFixed(decimals)) + "";
	
			if( (j = i.length) > 3 ){
					j = j % 3;
			} else{
					j = 0;
			}
	
			km = (j ? i.substr(0, j) + thousands_sep : "");
			kw = i.substr(j).replace(/(\d{3})(?=\d)/g, "$1" + thousands_sep);
			//kd = (decimals ? dec_point + Math.abs(number - i).toFixed(decimals).slice(2) : "");
			kd = (decimals ? dec_point + Math.abs(number - i).toFixed(decimals).replace(/-/, 0).slice(2) : "");
			return km + kw + kd;
		},

// this function to add to cart, you have already seen it above
	
    select: function (data) {  
	//...
	 } 
};
Sample config for the price configurator above
obRobotint.prices = [ 	 {
		'price_from': 0, // for all prices from 0 dollars
		'tint_system': 3, // apply only for a specific tinting system
		'set_price': 30, // set price 30 for all colors from 0 dollars
		'round': false,
		'scale': false,
	},	{
		'price_from': 0,
		'tint_system': 6, // rule is valid for Ceresit only 
		'set_price': 30,
		'round': false,
		'scale': false,
	}, {
		'price_from': 30, // for all prices from 30 dollars
		'tint_system': 3,
		'set_price': false, // do not set a fixed price
		'round': 'up',  // rounding up, down , math
		'scale': 10, // round up to 1 / 10 / 100 dollars
	},	{
		'price_from': 500,
		'tint_system': 3,
		'set_price': false,
		'round': 'up',  // rounding in up, down , math
		'scale': 100, // round up to 1 / 10 / 100 dollars
	},	{
		'price_from': 1000,
		'tint_system': 3,
		'set_price': false,
		'round': 'down',  // rounding in up, down , math
		'scale': 100, // round up to 1 / 10 / 100 dollars
	} ];
Staircase-type configurator
all prices up to 100 dollars will be divided into 3 groups 30 / 50 / 100 dollars per liter of tinting
all prices > 100 dollars will be rounded up to 10 to the top 110 / 120 / 130, etc.
obRobotint.prices = [
		{
				'price_from': 0,
				'tint_system': 3,
				'set_price': 30,
				'round': false,
				'scale': false,
		},{
				'price_from': 30,
				'tint_system': 3,
				'set_price': 50,
				'round': false,
				'scale': false,
		},{
				'price_from': 50,
				'tint_system': 3,
				'set_price': 100,
				'round': false,
				'scale': false,
		},{
				'price_from': 100,
				'tint_system': 3,
				'set_price': false,
				'round': 'up',  // rounding up, down , math
				'scale': 10, // round up to 1 / 10 / 100 dollars
		}
]

Example of configuring a price processor for a can of paint
Unlike the previous example, here we will round up the price not of a liter of tinting, but the price of tinting for the entire volume.
    var obRobotint = {
      // ... 
        processPrice: function($priceObj, data){ 
     
            var data_raw = $priceObj.data();           
            var ppl_raw = parseFloat(data_raw.pricePerLitr);
            var ppc_raw = parseFloat(data_raw.pricePerCan);
            var ppl = ppl_raw; // save it in a separate variable, which we will use
            var ppc = ppc_raw; // save it in a separate variable, which we will use
            var ref_vol = parseFloat(data_raw.priceRef_can_volume); // volume of product to be tinted .. according to the database
            

            var iVolume = ref_vol ;

            CVID = data.COLLECTION_VENDOR_ID 
            if(!CVID) CVID = 3 // in this case we take Tikkurila 
            
            var cur_set = false;
              
            for(var i in obRobotint.prices) {
                // config array of price levels and roundings	
                rt_price = obRobotint.prices[i];
                    if(rt_price['tint_system'] == CVID){
                        // if the price falls within the range, then take this block of the price configurator
                        if(ppc > rt_price.price_from ){
                            cur_set = rt_price
                        }
                    }
                }		

                if(!cur_set){
                    cur_set = {
                        'price_from': 0,
                        'tint_system': CVID , // in this case we take Tikkurila 
                        'set_price': false,
                        'round': false,
                        'scale': false,
                        };
                }
        
                        if(cur_set.set_price){
                            ppc = cur_set.set_price; 
                        }
                        
                        if(cur_set.round){
                            cur_set.scale  = parseInt(cur_set.scale);
            
                            if(!cur_set.scale  || cur_set.scale  == 0){
                                cur_set.scale = 1;
                            }				
        
                            if(cur_set.round == 'math'){
                                ppc = Math.round(ppc/cur_set.scale)*cur_set.scale; 
                            }else if(cur_set.round == 'up'){
                                ppc = Math.ceil(ppc/cur_set.scale)*cur_set.scale; 
                            }else if(cur_set.round == 'down'){
                                ppc = Math.floor(ppc/cur_set.scale)*cur_set.scale; 
                            }else{
                                ppc = Math.round(ppc/cur_set.scale)*cur_set.scale; 
                            }
                        }

                // price of tinting per liter  
                ppl = ppc/iVolume;
                        
                if(ppc!=ppc_raw){
                    // rewrite the button value to client values, adjusted to the level we need
                    $priceObj.attr("data-price-shop",ppc);
                    $priceObj.text(obRobotint.numberFormat(ppc,0,"."," ")+" $");
                }
            },
// .... 
}
Tinting products of different Brands:


RoboTint currently supports Tikkurila, Akzo Nobel and Ceresit (Henkel), Vincent Decor, VGT, Meffert, Ebe tinting systems. This means that tinting will be available for all tinted products belonging to the brands of these companies (subject to their availability in the RoboTint database).

In order to setup the online-tinting of materials from other brands while using the machines and pigments from of the tinting systems mentioned above, you must perform the following sequence of actions:


  • Within the BARCODE value, a barcode of the product belonging to one of the supported tinting systems should be transferred to the button. The product is selected according to the opinion of your technologist and it should be the one that is matching the accrual base product in the closest way possible. Usually, for a group of products that have the same purpose, one substitute product is indicated, the barcode of which is used in the process of calculating the tinting

  • The value of the tinting cost should be processed from the PRICE_PER_LITER parameter in order to eliminate the error in calculating the cost due to a different packing volume
JSON-requests. Request colorants prices
If necessary, you can send a request to calculate the price of tinting in JSON format. To exchange, you must use authorization in the request headers. The authorization key is not equal to the secret code used for Javascript integration.

Example implementation in PHP:


$client = new HttpClient();

$client->setHeader("Authorization", "e2727d915b415************************************1fa2975ba507ba");
$client->setHeader("Content-type", "application/json");


$arData = [
    "CLIENT_ID"	=> "4",
    "COLOR_ID" 	=> "140660",
    "BARCODE"	=> "6408070012765",
    "action" 	=> "get-color-price"
];

$result = $client->post("https://core.robotint.ru/exchange/", json_encode($arData));
Parameters and methods description:

in order to receive up to date information - follow link to swagger description.