Table of Contents

Calculate Distances With Google Maps API

Abby Updated by Abby

By first extracting the data from our user's address and then creating a function we'll be able to calculate the distances in kilometers from one point to another.

Here's what the flow will look like:

Cloud Console

Go to the Google Cloud Console, enable your APIs, and activate billing.

You'll need to activate 'Places API', 'Maps JavaScript API', and 'Geocoding API'.

Please check out theirΒ official documentationΒ for more information.

Address Block

Set up the 'Address Question' block,Β here's how.

Encode Address

Next, you'll need to encode the address in order to send the request to Google Maps, you'll add a 'Code block' with the following snippet:

window.uriaddress = encodeURIComponent("@{address}");
this.setCustomData({ newvar: uriaddress});
console.log(uriaddress);

User Input

In order to make use of the variable we created in the previous step we need a user input. This can be any question type, but here's what we used:

API Key

Add your API key again.

Webhook Request

Now we'll do a webhook request with our encoded address, you'll need to connect the previous block to a 'Webhook block' and add the following in the input section on top, selecting 'Get':

https://maps.googleapis.com/maps/api/geocode/json?address=@{newvar}&key=@{googlemapsapikey}

You can thenΒ test your requestΒ and save 'Results' as @response.

You can connect the red flow to an error message, or back to the address questions block, and then connect the green flow to the following:

Set Our Latitude and Longitude

We need to set our own latitude and longitude, we'll save them at @lat1 and @lon1, we'll connect these set variables to the code block:

Code Block

Next, you'll need another 'Code block', in this block we will set the variables as well as calculate the distances

In this block you'll add the following snippet:

var True = false; 
var False = true;
var None = null;
var response = @{response};
var details;

console.log(response);

if (response[0].hasOwnProperty('property1partial_match') && response[0].partial_match === True){
details = "partial match";
console.log("partial match");
} else if (response[0].types[0] == "postal_code" || response[0].partial_match === False || response[0].partial_match === undefined ){
details = response[0].address_components
console.log(details);
} else {
details = "no results";
console.log("no results");

}

console.log("details:",response);

var details_Address_Obj = {}
if (details !== "no results" && details !== "partial match"){

for (var i = 0; i < details.length; i++){

details[i][details[i].types[0]] = details[i]["long_name"]
details_Address_Obj[details[i].types[0]] = details[i][details[i].types[0]]
}

details_Address_Obj["formatted_address"] = response[0]["formatted_address"]
details_Address_Obj["latitude"] = response[0].geometry.location.lat
details_Address_Obj["longitude"] = response[0].geometry.location.lng
console.log(details_Address_Obj);

this.setCustomData( {
address_results: "Ok",
address_administrative_area: details_Address_Obj.administrative_area_level_1 || " ",
address_country: details_Address_Obj.country || " ",
address_formatted_address: details_Address_Obj.formatted_address || " ",
address_latitude: details_Address_Obj.latitude || " ",
address_locality: details_Address_Obj.locality || details_Address_Obj.postal_town || details_Address_Obj.administrative_area_level_2,
address_longitude: details_Address_Obj.longitude || " ",
address_sublocality: details_Address_Obj.political || " ",
address_postal_code: details_Address_Obj.postal_code,
address_route: details_Address_Obj.route || " ",
address_street_number: details_Address_Obj.street_number || " "
});
} else if (details === "no results"){
this.setCustomData ({
address_results: "Fail";
})
} else if (details === "partial match") {
this.setCustomData( {
address_results: "Partial";
})
}
//This function takes in latitude and longitude of two location and returns the distance between them as the crow flies (in km)
let lat1 = @{lat1};
let lon1 = @{lon1};
let lat2 = details_Address_Obj.latitude;
let lon2 = details_Address_Obj.longitude;
let distance;
function calcCrow(lat1, lon1, lat2, lon2)
{
console.log(lat1, lon1, lat2, lon2) ;
var R = 6371; // km;
var dLat = toRad(lat2-lat1);
var dLon = toRad(lon2-lon1);
var lat1 = toRad(lat1);
var lat2 = toRad(lat2);

var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;

distance = d.toFixed(1);
}

// Converts numeric degrees to radians
function toRad(Value)
{
return Value * Math.PI / 180;
}
calcCrow("@{lat1}", "@{lon1}", "@{lat2}", "@{lon2}");
this.setCustomData({distance:distance});
User Input

After every code block we need a user input before the variables can be used within the bot, here's what we used:

Add Condition

We then set a 'Condition' using one of the variables from the Javascript block, we'll connect the green arrow to the next point in your flow and the red to an error message or the address block, up to you!

If this condition is true then your flow will continue. Remember the conditions are case-sensitive so it's important to input exactly as it is below:

Code Block

After we've set our variables we'll connect them to a code block where we'll calculate the distance and create a new Landbot variable

Here's what we need to put inside of the code block:

//This function takes in latitude and longitude of two location and returns the distance between them as the crow flies (in km)
let distance;
function calcCrow(lat1, lon1, lat2, lon2)
{
console.log(lat1, lon1, lat2, lon2)
var R = 6371; // km
var dLat = toRad(lat2-lat1);
var dLon = toRad(lon2-lon1);
var lat1 = toRad(lat1);
var lat2 = toRad(lat2);

var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;

distance = d.toFixed(1);
}

// Converts numeric degrees to radians
function toRad(Value)
{
return Value * Math.PI / 180;
}
calcCrow("@{lat1}", "@{lon1}", "@{lat2}", "@{lon2}")
this.setCustomData({distance:distance});

User Input

Remember to create a Landbot variable with Javascript we need a user input after the code block, which is why we add the button with only one option.

That's it! Now your distance will variable will be available in Landbot with the name @distance.

Here's what the results look like:

How did we do?

Extract Data With Google Maps Geocoding API

Contact