Public | Automated Build

Last pushed: 2 years ago
Short Description
Short description is empty for this repo.
Full Description



A simple, Node-based service for providing geolocation data based on a user's IP address. Backed by the MaxMind DB. Also includes a JavaScript plugin for querying the service and handling the response.


  • Capable of handling homepage traffic
  • Works with and without RequireJS
  • Decorates <html> tag with geo-patterned classes, like Modernizr and NYT5
  • Enables CSS fairly complex display rules for states before/after class logic
  • Pretty fast


Please add Issues to this repo on Github.

Local Development

Client-side JS

Local development

JavaScript dependencies like grunt can be installed via NPM:

npm install

Changes should be made to frontend/geoip.js.

Please add tests to frontend/spec/geoipSpec.js (Tests currently not working).


Minify your latest version of the script by running grunt uglify.

Once you have uglified the script, upload it to or

To upload it, run rake publish DEPLOY_HOST=[ or] AWS_CONFIG_PATH=[keys].

For details about the keys, see the documentation in Preview [NYT ONLY].


The Jasmine tests can be run via PhantomJS using grunt: grunt jasmine. (Tests currently not working).



Since the server requires GNU tar, you'll likely find it easiest to develop locally on OS X by building and then running a docker image:

docker build -t geoip . && docker run --name geoip --rm -p 80:80 -e MAXMIND_DATABASE_URL=...S3-path-to/GeoIPCity.tar.gz -e AIRBRAKE_PROJECT_ID=...your_id... -e AIRBRAKE_API_KEY=..your_key... -e ORIGIN_RE="/^https?:\/\/([\w-]+\.)*yourdomain\.com(:\d+)?$/" -e NODE_ENV=production geoip

To develop locally against your docker image, ping your locally running service like this:

curl -vv -H "Origin:" [your_docker_image_IP]:80/?ip=

You should then get a response like

{"response":true,"data":{"country_code":"US","country_code3":"USA","country_name":"United States","region":"NY","city":"New York","postal_code":"10018","latitude":40.75529861450195,"longitude":-73.99240112304688,"metro_code":501,"dma_code":501,"area_code":212,"continent_code":"NA","time_zone":"America/New_York","zone_abbr":"ET","fips_state":"36","fips_county":"061"},"status":"ok"}

For more details and deployment steps for the server image, check out the DevOps wiki [NYT only].

On other platforms

Run npm start.


Client-side JS

How to Include the JS

This plugin is intended to be used on NYT5 pages, and has a RequireJS module variant. It can also be used in a non-RJS environment.

The script itself defines but does not require an AMD module, so to initialize it you need to require the module:

For example:

<script type="text/javascript" src=""></script>
<script type="text/javascript">
(function() { require(['nytint-geoip']); })();

Use the same basic format to add your own custom logic for handling the response from our geoip service:

<script type="text/javascript" src=""></script>
<script type="text/javascript">
(function() {
  require(['nytint-geoip'], function(geoip) { 
  var handler = function(d) {
    console.log('lat/lon',d.latitude, d.longitude);

Default behavior

When the client-side script is instantiated on the page, it will automatically apply a subset of geocoded data as classes to the html tag. Styles can then be written to show/hide elements depending on geolocation per session.

Here are the properties promoted to classes on html:

  • geo-continent-NA: Continent as a code, from this list
  • geo-country-US: Country as a code, from this list
  • geo-region-NY: State/province or equivalent as a code
  • geo-dma-501: Media Market code, from this list
  • geo-postal-10014: Postal code, for 34 countries in this list
  • geo-timezone-America/New_York: the reader's timezone
  • geo-us-timezone-ET: the American reader's timezone in shorthand

For a response from the geoip service that looks like this:

  "response": true,
  "data": {
    "country_code": "US",
    "country_code3": "USA",
    "country_name": "United States",
    "region": "NY",
    "city": "New York",
    "postal_code": "10018",
    "latitude": 40.755298614502,
    "longitude": -73.992401123047,
    "metro_code": 501,
    "dma_code": 501,
    "area_code": 212,
    "continent_code": "NA",
    "time_zone": "America\/New_York",
    "zone_abbr": "ET",
    "fips_state": "36",
    "fips_county": "061"
  "status": "ok"

the following will use it to control content options:

  /*default display conditions*/
  .story[data-story-id="100000004295572"] {display: block;}
  .story[data-story-id="100000004295573"] {display: none;}
  /*geocoded display conditions*/
  html.geo-dma-501 [data-story-id="100000004295572"] {display: none;}
  html.geo-dma-501 [data-story-id="100000004295573"] {display: block;}
<div class="story" data-story-id="100000004295572">I will be shown for other readers.</div>
<div class="story" data-story-id="100000004295573">I will show for readers in the NYC DMA.</div>
<script type="text/javascript" src=""></script>
<script type="text/javascript">
(function() {

If you want the visibilty of one element to always be the inverse of another's (depending on the criteria defined for the latter), you can show/hide content with :not() rules within your CSS.

  /*default display conditions*/
  .story[data-story-id="100000004295576"] {display: none;}
  /*geocoded display conditions*/
  html.geo-region-NY [data-story-id="100000004295574"],
  html.geo-region-VA [data-story-id="100000004295575"],
  html:not(.geo-region-KS) [data-story-id="100000004295576"] {display: block;}
<div class="story" data-story-id="100000004295574">I will show for readers in NYC.</div>
<div class="story" data-story-id="100000004295575">I will be hidden for readers in NYC.</div>
<div class="story" data-story-id="100000004295576">I will show for readers not in Kansas.</div>
<script type="text/javascript" src=""></script>
(function() { 

Other Relevant Documentation

Links here to external documentation that might help someone using or developing in this project. For example:

  • Jasmine - A behavior-driven development framework for testing JavaScript code


Include and licence information here.

Docker Pull Command
Source Repository