Web applications are becoming more and more personalized. Also, there is a rise of web applications that use location-based services for multiple reasons. It can be either for privacy, security or any specific location-based features.
By knowing the user’s location you can easily offer different features such as personalized content, good security, weather forecasts, more localization and a better user experience. As a developer, it is crucial to know how to get the user’s location for your web applications. In this article, we will take you through step-by-step instructions on how you can get the user’s location using modern web technologies such as React.js. We will cover different methods to get the user’s IP address and how we can get more geolocation data from the user. So, let’s get started!
First, let’s understand what is an IP or IP address.
Each device that uses an internet has a unique address just like every house has a unique number or address. This unique address of the device is called IP address. It helps devices to communicate with each other over the internet.
Here, the IP stands for “Internet Protocol“ which is a set of rules that devices use to communicate with each other over the Internet. Now let’s understand Geolocation.
The Geolocation is combination of two words. First is “Geo” which means the earth and the second word is “location” which means where something is located on earth.
So, the “IP-Geolocation” is a way to find where the device is located physically based on its IP address. The accuracy of IP-Geolocation data depends on different factors such as which method is used to get the data, the quality of the data, the type of device etc. The data can be less accurate for mobile devices since these devices frequently change networks. Now let’s see how we can get the user’s IP address in React.
There are several methods by which we can get the user’s location. For this article we are going to use the Geolocation API which is supported by all browsers and we don’t have to install any other 3rd party library to use it. To get more data we can use APIs from 3rd party services like Geocoding API.
First let’s create a React app using vite. Open the CMD or terminal then locate your project folder and use the following commands.
npm create vite@latest your-app-name
Once you execute the above command it will show you a list of frameworks, now select React from the list using arrow keys and press enter.
Now it will show you a list of variants, select Javascript from those variants. Then it will create a folder with your app name and add all the necessary files. Now use the following commands to install all the required libraries and run the development server.
cd your-app-name
This command will change the current directory to the app directorynpm install
Using this command we will install all the required librariesnpm run dev
This command will start the development server probably at localhost:5173
Now the development server is up and running so let’s get the user’s IP address.
The Geolocation API allows the user to provide their location if they wanted to. This method only works if the user give permission to access his location otherwise this browser-based API won’t be able to get the IP address. If the feature on your web application really require the user’s location then you can prompt the user with a good text message and let them know why you require their location.
This Geolocation API is accessed via a call to navigator.geolocation
which is a property that can return a Geolocation object. Let’s see what is navigator.
navigator: It is an interface that represents the state and the identity of the user agent (browser). Let’s log this navigator and see what other properties it provides.
Open the App.jsx file and clean all the code inside the return statement and just keep the parent div
with the class App
then use the console.log(navigator)
inside a useEffect
as given in the following code.
import { useEffect } from "react";
import "./App.css";
function App() {
useEffect(() => {
console.log(navigator);
}, []);
return <div className="App"></div>;
}
export default App;
In your development server tab open the console by pressing F12 or with the right click of the mouse. You will see the list of different properties such as appCodeName, Bluetooth, clipboard, geolocation etc. Let’s log the geolocation. Just add the geolocation in the log like this console.log(navigator.geolocation)
. In the console you will see an empty object because we don’t have permission to access the geolocation for now so let’s see how to get this permission. Check out the following code and the explanation.
useEffect(() => {
if (navigator.geolocation) {
navigator.permissions
.query({ name: "geolocation" })
.then(function (result) {
console.log(result);
});
} else {
console.log("Geolocation is not supported by this browser.");
}
}, []);
In the above useEffect
, first we will check if there is navigator. geolocation or not and if it’s true we will check the permissions.
Here,
navigator.permissions: It returns a Permissions object that can be used to query and update the permission status.
query: It is a method of Permission which returns the state of a user permission. It takes an object that has comma separated list of name-value pairs. Here we have passed geolocation since we want to know the status of geolocation permission.
Here we are getting a Promise that is why we will use then
keyword and log the results. If you check the console of the browser you will see the following object.
{
name: "geolocation",
onchange: null,
state: "prompt"
}
The state can have 3 different values,
For the “granted” and “prompt” states we can create a function to get the current position of the user but for the “denied ”state, we can show instructions how they can enable location permission in their browser.
NOTE: There is no way you can prompt for location permission again if the user has already denied the location permission unless the user enables it manually in his browser.
Let’s use 3 conditions for all 3 permission states as the following
useEffect(() => {
if (navigator.geolocation) {
navigator.permissions
.query({ name: "geolocation" })
.then(function (result) {
console.log(result);
if (result.state === "granted") {
//If granted then you can directly call your function here
} else if (result.state === "prompt") {
//If prompt then the user will be asked to give permission
} else if (result.state === "denied") {
//If denied then you have to show instructions to enable location
}
});
} else {
console.log("Geolocation is not supported by this browser.");
}
}, []);
In the prompt
state let’s use the function called getCurrentPosition. This function takes the following arguments.
Let’s implement all 3 arguments. First let’s create a success function. Before the useEffect
add the following success function.
function success(pos) {
var crd = pos.coords;
console.log("Your current position is:");
console.log(`Latitude : ${crd.latitude}`);
console.log(`Longitude: ${crd.longitude}`);
console.log(`More or less ${crd.accuracy} meters.`);
}
This callback function will return a position object that has coords which means coordinates. You can get values such as latitude, longitude, accuracy etc from coordinates. Now add the following error function after the success function.
function errors(err) {
console.warn(`ERROR(${err.code}): ${err.message}`);
}
Let’s declare an option object as well,
var options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0,
};
Now paste the following line in the “prompt” and “granted” conditions and check the output in your browser.
navigator.geolocation.getCurrentPosition(success, errors, options)
You can see one prompt in the browser asking you for location permission. Once you give the permission you can see coordinate values in the console tab. Here is the full code.
import { useEffect } from "react";
import "./App.css";
function App() {
var options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0,
};
function success(pos) {
var crd = pos.coords;
console.log("Your current position is:");
console.log(`Latitude : ${crd.latitude}`);
console.log(`Longitude: ${crd.longitude}`);
console.log(`More or less ${crd.accuracy} meters.`);
}
function errors(err) {
console.warn(`ERROR(${err.code}): ${err.message}`);
}
useEffect(() => {
if (navigator.geolocation) {
navigator.permissions
.query({ name: "geolocation" })
.then(function (result) {
console.log(result);
if (result.state === "granted") {
//If granted then you can directly call your function here
navigator.geolocation.getCurrentPosition(success, errors, options);
} else if (result.state === "prompt") {
//If prompt then the user will be asked to give permission
navigator.geolocation.getCurrentPosition(success, errors, options);
} else if (result.state === "denied") {
//If denied then you have to show instructions to enable location
}
});
} else {
console.log("Geolocation is not supported by this browser.");
}
}, []);
return <div className="App"></div>;
}
export default App;
That’s it. This is how you can easily get the latitude and longitude value of any device. Now this information is not enough so let’s use opencage’s reverse geocoding APIs to get more information on user’s location.
We already got the latitude and longitude info about the user’s device now let’s see how we can use it to get more information about its location. We will use APIs from opencage to get more info on the location. So, make sure you signup and get an API key. You don’t have to pay for anything since opencage provides 2,500 requests/day in the free trial. You can checkout more info about the pricing form their website. I have used Opencage’s API since they have free trial and no CORS restriction as well. Now let’s create a function to use this API.
const [location, setLocation] = useState();
function getLocationInfo(latitude, longitude) {
const url = `https://api.opencagedata.com/geocode/v1/json?q=${latitude},${longitude}&key=${APIkey}`;
fetch(url)
.then((response) => response.json())
.then((data) => {
console.log(data);
if (data.status.code === 200) {
console.log("results:", data.results);
setLocation(data.results[0].formatted);
} else {
console.log("Reverse geolocation request failed.");
}
})
.catch((error) => console.error(error));
}
This getLocationInfo function takes latitude and longitude then it uses the URL from the opencage’s documentation which takes latitude, longitude and the API key. In this function we have used fetch to get the data from the URL and if the status code is 200 then we will store the data in the location state. You can check your console on the browser to see which type of data you are getting. For now, we are using the value from the formatted property. To get more info about the response object you can check the documentation. Now let’s call this function from the success function that we have already defined.
function success(pos) {
var crd = pos.coords;
...
...
getLocationInfo(crd.latitude, crd.longitude);
}
Now, whenever the user agrees to give his location the success function will run and also it will pass the latitude and longitude info to the getLocationInfo function and execute it. You can use this location state to display the location in your web app.
import { useEffect, useState } from "react";
import "./App.css";
const APIkey = "Enter-your-api-key";
function App() {
const [location, setLocation] = useState();
function getLocationInfo(latitude, longitude) {
const url = `https://api.opencagedata.com/geocode/v1/json?q=${latitude},${longitude}&key=${APIkey}`;
fetch(url)
.then((response) => response.json())
.then((data) => {
console.log(data);
if (data.status.code === 200) {
console.log("results:", data.results);
setLocation(data.results[0].formatted);
} else {
console.log("Reverse geolocation request failed.");
}
})
.catch((error) => console.error(error));
}
var options = {
enableHighAccuracy: true,
timeout: 5000,
maximumAge: 0,
};
function success(pos) {
var crd = pos.coords;
console.log("Your current position is:");
console.log(`Latitude : ${crd.latitude}`);
console.log(`Longitude: ${crd.longitude}`);
console.log(`More or less ${crd.accuracy} meters.`);
getLocationInfo(crd.latitude, crd.longitude);
}
function errors(err) {
console.warn(`ERROR(${err.code}): ${err.message}`);
}
useEffect(() => {
if (navigator.geolocation) {
navigator.permissions
.query({ name: "geolocation" })
.then(function (result) {
console.log(result);
if (result.state === "granted") {
//If granted then you can directly call your function here
navigator.geolocation.getCurrentPosition(success, errors, options);
} else if (result.state === "prompt") {
//If prompt then the user will be asked to give permission
navigator.geolocation.getCurrentPosition(success, errors, options);
} else if (result.state === "denied") {
//If denied then you have to show instructions to enable location
}
});
} else {
console.log("Geolocation is not supported by this browser.");
}
}, []);
return (
<div className="App">
{location ? <>Your location: {location}</> : null}
</div>
);
}
export default App;
You can implement an error state as well which display the error message when the API or function can not fetch the data properly. Also implement the required error handling method on the functions as well. This is how you can get a lot of information about the device’s location. Now let’s see how you can get the device’s IP address.
To get the user’s IP address on the client side we will use the ipify which is a simple public IP address API. We will create another useEffect
and create a function to fetch the IP address as shown in the following code block.
const [ipAddress, setIpAddress] = useState('');
useEffect(() => {
const fetchIp = async () => {
try {
const response = await fetch('https://api.ipify.org?format=json');
const data = await response.json();
setIpAddress(data.ip);
} catch (error) {
console.error(error);
}
};
fetchIp();
}, []);
In the above code, we have created one state called ipAddress
to store the IP address. The ipfy is a public API so we don’t need any API key and we can directly use the URL. In useEffect
we have created one async function called fetchIp
which will fetch and store the IP address in the ipAddress
state. Don’t forget to call the fetchIp
function in the useEffect
.
This is how you can easily get the device’s IP address. There are multiple APIs that provide such services. For the server side, you can generally obtain the IP address from the request that the user sent you to get the webpage or any data. However, you should not rely solely on the IP address since some ISPs use shared IP addresses, which means multiple users may have the same IP address. Additionally, some users use VPNs and proxies as well.
When it comes to the user’s data it is always a crucial part in any application. As a developer, it is our job to create an application that is user-centric and protects users’ data. For the data like the device’s location developer can face many problems such as,
Implementing location-based features can be challenging, but by following the best practices you can provide users more personalized and secure experience. Keep the following points in mind when handling location based data.
Accuracy: When using the IP address you should double check it by using more than one api and cross-check the location. You must include a fallback mechanism in location based services and features. It is better to verify the data since location data can be affected by factors such device settings, network connections etc.
Privacy: This is the major concern when collecting any user’s data since you have to keep in check with the different laws of multiple countries. Developers should always respect the user’s privacy. It is necessary to have a clear and concise privacy policy when it comes to collecting any data from the user. You must tell the user whenever you are collecting any sensitive information. If there are any location based features then you should clearly show why and how you are going to use the data. Also, you should provide an opt-out option for the user so if they don’t want to share their data they can opt out easily.
Security: For the security of the data you can implement authentication mechanisms like OAuth or JWT and secure the API endpoints from any unauthorised access. You should always suggest user to use strong passwords, updating browsers etc. You must encrypt the data using HTTPS and SSL certificates to ensure secure communication between the client and the server. In the backend, you can implement role-based access control so that only selected user such as only admins can access the data. Before updating any dependency you should always check if it is from the official source or not.
The location data plays a major role when it comes to users’ personalized experience, however, handling this data is also a crucial task. There are many different methods that you can use to get the location data but it depends on how much data you will need if you need just an IP address then you can use the ipify APIs and if you need more geolocation data then you can use either opencage or google’s reverse geocoding API as well. If you are building small applications such as a weather apps then you don’t need to use any APIs since you can use the browser’s Geolocation APIs. When it comes to the security and privacy of these data you should avoid any potential risks associated with the user’s privacy by providing a well-written privacy policy. That’s the end of this article hope you like it.