Monitor your key's usage before you hit a limit
Watching your quota headers as you go tells you when a limit is approaching, well before a request actually gets rejected.
Geolocation belongs on the server for most use cases, personalization, defaults, and analytics among them, since it needs no cooperation from the visitor's browser and no script running client-side at all.
Regardless of language, the call is the same plain HTTP GET request to /v1/ip, with the key sent as a header.
GET /v1/ip?ip=203.0.113.60
X-API-Key: mg_live_examplekey123{
"status": "ok",
"ip": "203.0.113.60",
"version": 4,
"found": true,
"country": "Netherlands",
"country_code": "NL",
"region": "North Holland",
"city": "Amsterdam",
"postcode": "1012",
"lat": 52.3702,
"lon": 4.8952,
"timezone": "Europe/Amsterdam",
"asn": 3344,
"org": "Example ISP"
}Fetch the visitor's own address from the request, typically $_SERVER['REMOTE_ADDR'], and pass it as the ip parameter, then make the HTTP request using whichever HTTP client your PHP setup already uses, curl or a library wrapper around it. Since this site itself is built as server-rendered PHP with no client-side JavaScript, this pattern fits naturally into a page's normal rendering flow, with the location data available before the page markup is generated.
Read the visitor's address from the incoming request object, commonly req.socket.remoteAddress or a header set by a reverse proxy such as X-Forwarded-For if one sits in front of your app, and make the same GET request using your HTTP client of choice before rendering a response.
If your app sits behind a load balancer or reverse proxy, the address your code sees directly might be the proxy's own address rather than the visitor's. Check whatever forwarded-address header your proxy sets and pass that address explicitly as the ip parameter, rather than relying on the connection's raw remote address, which would otherwise geolocate your own infrastructure instead of the visitor.
The lookup itself costs the same one request whether it is called from PHP or Node, or any other backend language, since cost is tied to the request reaching the API, not to what made the call. Cache the result for the length of a session in either language to avoid repeating the lookup on every page.
Server-side geolocation works the same way regardless of backend language, one HTTP call with the visitor's address. Full authentication options are on the authentication docs, and the field list is on the IPv4 lookup docs.