Advanced Tutorial: Automatic Delivery Charge Based on Distance via Google Maps



I have managed to find the solution/work around using shell subtitle feature using below tutorial as an example.

1.Created an “Update Application Subtitle” action (header Distance)
2.Created a second “Update Application Subtitle” action (clear Ticket header)
3…Created a “calculated distance” rule (Header Distance)
4. Created a “Ticket Closed” rule (Clear Ticket Header)

Header Distance - Event Name set to Ticket Displayed

Delivery Orders Distance Rule - set the Event Name to Ticket Created

Now when Ticket is opened calculated Distance is always displayed.

I have identified an error with one of the rule. happy with the solution/workaround. Thanks…


my distance calculation is not working can you help



Sure what do you want help with?


Trying to implement this, and this does work with ‘Order Added to Ticket’ event and updates the distance field.

Having trouble trying to get this rule to fire when ‘Ticket Entity Changed’, as checking after every order item is going to flood google with API requests.

Or is there a way to get the distance field to populate on the ‘new customer’ screen?

Can I call the script here?

Many Thanks


You can get distance just about any time you wish. It can even be stored meaning it only checks it once.


Hi @Jesse I have edited my post to show a screenshot; can i call the script in the entity custom field?


You probably would not want to do that. Anytime it would read that field it would run the script. It would be better to run it once and store it then feed the stored value in the Custom Data Field.

You can do that with Entity Updated event maybe? Execute an update program setting and store it in the database.


I understand, I will have a play about - its trying to find an event that the rule can use that is well before order added to ticket - I’ll keep trying! Thanks

Entity Updated doesn’t seem to work


Yes you need an event that is not repetitive a single time event. THen store the result in a program setting and you can reference that program setting so it doesnt have to run the API every singe time. You could also store it as a task.


Try the ticket entity changed event but use that event to update a program setting instead of the entity itself. Use the program setting in the Custom Data Field.


I have no idea :weary: I’ll have a break and come back to it with fresh eyes later, just frustrating that the script is working but is not updating the entity when I need it to


I can help you with it later tonight if your still needing help. I have to go out of town now and wont have access to a system.


Sorry if I’m missing something but since your already using a script on postcode can’t you add to that script and map the value?


@JTRTech i did think this could have been an option and is probably what I need to use (so that Distance could be mapped then as $5, at same time as street name etc) I have attempted to do this a couple of times but I’m not up to speed with scripting so struggling to pull the distance data.


You already have both scrips so should be easy.
Add distance script as another function and call that function from postcode lookup script as your distance in return.
Paste scripts.


Edit… I’ve got the following script working, however it only works when postcode has all capital letters - lowercase postcodes return with the postcode value tested.

function Read(postcode)
var country = ‘GB’;
var urlfmt = '’+ YOUR_API_KEY + ‘&components=postal_code:’+postcode;

if(country != undefined)
urlfmt += ‘|country:’+country;
var content = web.Download(urlfmt);
var obj = JSON.parse(content);
var lat = obj.results[0];
var lng = obj.results[0].geometry.location.lng;

var addrurl = ‘’ + YOUR_API_KEY + ‘&latlng=’ + lat + ‘,’ + lng + ‘&sensor=false’;

var addr = web.Download(addrurl);
var addrObject = JSON.parse(addr);

var data = GetAddressComponents(addrObject.results,postcode);
if(data == null) return postcode;

var street = ReadComponent(‘route’,data);
if(street == ‘-’)
street = ReadComponent(‘locality’,data);
if(street == ‘-’)
street = ReadComponent(‘administrative_area_level_4’,data);
var town = ReadComponent(‘postal_town’,data);
var county = ReadComponent(‘administrative_area_level_2’,data);
var distance = gdistance(postcode);

return postcode + ‘,’ + street + ‘,’ + town + ‘,’ + county + ‘,’ + distance;

function GetAddressComponents(results,postcode)
for(i=0;i < results.length;i++)
for(j=0; j< results[i].address_components.length;j++)
var component = results[i].address_components[j];
if(component.long_name.replace(’ ‘,’’) == postcode.replace(’ ‘,’’))
return results[i].address_components;
return null;

function ReadComponent(name,components)
var component = components[i];

     if(component.types[j] == name)
       return component.long_name;


return ‘-’;

function gdistance(postcode)



var u = ‘’ + YOUR_API_KEY + ‘&origins=NP201FU.&destinations=’+postcode+’.&mode=driving&language=en-GB&sensor=false&units=metric’;

var alldata = web.Download(u);

var json = JSON.parse(alldata);

// distance.text gives data like 826 km
// var distance = json.rows[0].elements[0].distance.text;

// distance.value gives data like 826467 (which is meters, so divide by 1000 to get Km)
var distance = json.rows[0].elements[0].distance.value/1000;

return distance;



Shouldn’t actually cause much of an issue I don’t think; the postcode field is formatted to only use uppercase letters anyway :joy:


You could also force capitals in script. The function is something like .toCapitals(), Google will give answer.


All done, thanks for your help!
Just for reference the function is .toUpperCase();
I even went a bit further and used the script to call the travel time data as well.