npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@mrazakassar/audience-identifier-core

v1.2.2

Published

Core audience identification engine with WORLDWIDE reverse geocoding. Auto-detects postal codes globally, generates geohash IDs, and matches audience segments by location, time, and behavior. Works with React Native and Strapi.

Readme

Audience Identifier Core

A powerful NPM package for identifying audience segments based on geographic coordinates, timestamps, and behavioral patterns. Now with WORLDWIDE reverse geocoding and Geohash ID generation. Works seamlessly with React Native, Strapi, and any Node.js environment.

✨ What's New in v1.2.0

🌍 WORLDWIDE Reverse Geocoding - Works globally for ANY latitude/longitude on Earth
🆔 Auto Geohash Generation - Unique geo IDs for location-based indexing & proximity search
📍 Auto ZIP/Postal Code Detection - No external API needed (uses FREE Nominatim/OpenStreetMap)
Zero Configuration - Just coordinates → everything else happens automatically

Features

13 Pre-defined Audience Segments - Affluent Passengers, Commuters, Airport Travelers, and more ✅ 6 Daypart Classifications - Early Morning, Midday, Evening Peak, Prime Time, Late Night, Overnight ✅ 15 Geographic Zones - Mapped across major cities (extensible globally) ✅ WORLDWIDE Reverse Geocoding - FREE, no API key, works anywhere on Earth ✅ Auto Geohash IDs - Unique identifiers for any location (precision 1-12) ✅ Auto ZIP Detection - Automatically detects postal codes from coordinates ✅ Zero Dependencies - Pure JavaScript/Node.js ✅ Cross-Platform - Works in React Native, Strapi, Node.js, and browsers ✅ High Performance - Built-in caching for ZIP-to-zone lookups ✅ Batch Processing - Aggregate statistics from multiple locations

Installation

Using npm

npm install @ivee/audience-identifier-core

Using yarn

yarn add @ivee/audience-identifier-core

Quick Start

NEW! Simplest API (v1.2.0+) - AutoDetect Everything

No need to manually get ZIP codes anymore! Just pass coordinates and time:

import { identifyAudience } from '@ivee/audience-identifier-core';

// Inside a component or async function
const getAudience = async () => {
  // That's it! ZIP code is auto-detected worldwide
  const result = await identifyAudience(
    40.7128,          // Latitude (anywhere on Earth)
    -74.0060,         // Longitude (anywhere on Earth)
    new Date()        // Timestamp
  );

  console.log(result.audiences);      // Matched audience segments
  console.log(result.geohashID);      // Unique geo ID: "dr5regw"
  console.log(result.coordinates);    // { lat, lng, zipCode: "10000" }
};

1. React Native Example

import { identifyAudience } from '@ivee/audience-identifier-core';

// Inside a component or async function
const getAudience = async () => {
  const result = await identifyAudience(
    40.7580,           // Latitude
    -73.9855,          // Longitude
    new Date(),        // Timestamp
    {
      rideMode: 'work'  // Optional: 'work', 'watch', 'shop'
    }
  );

  console.log(result.audiences); // Array of matched audience segments
  // Output: [{ id: 'AUD-06', name: 'Financial / Work / Business', tier: 'Intent', ... }]
};

2. Strapi Example

// In your Strapi controller or service

const AudienceService = ({ strapi }) => ({
  async identifyUserAudience(lat, lng, timestamp) {
    const { identifyAudience } = require('@ivee/audience-identifier-core');
    
    // ZIP code is auto-detected worldwide!
    const result = await identifyAudience(lat, lng, timestamp);

    return result;
  }
});

module.exports = AudienceService;

3. Simple Node.js Example

const { identifyAudience, batchIdentifyAudiences } = 
  require('@ivee/audience-identifier-core');

// Single identification with auto ZIP detection
(async () => {
  const result = await identifyAudience(
    40.7128,
    -74.0060,
    '2026-02-05T18:45:00Z'
  );
  
  console.log('Postal Code:', result.coordinates.zipCode);  // Auto-detected!
  console.log('Geohash ID:', result.geohashID);             // Geo ID: "dr5regw"
  console.log('Matched Audiences:', result.audiences);
  console.log('Daypart:', result.daypart.name);
})();

4. Worldwide Location Example

const { identifyAudience } = require('@ivee/audience-identifier-core');

(async () => {
  // Works ANYWHERE on Earth
  const places = [
    { name: 'New York', lat: 40.7128, lng: -74.0060 },
    { name: 'London', lat: 51.5074, lng: -0.1278 },
    { name: 'Tokyo', lat: 35.6762, lng: 139.6503 },
    { name: 'Sydney', lat: -33.8688, lng: 151.2093 }
  ];

  for (const place of places) {
    const result = await identifyAudience(place.lat, place.lng, new Date());
    console.log(`${place.name}: ${result.coordinates.zipCode} (${result.geohashID})`);
    // Output:
    // New York: 10000 (dr5regw)
    // London: WC2N 5DX (gcpvj0d)
    // Tokyo: 168-0063 (xn76cy8)
    // Sydney: 2000 (r3gx2fb)
  }
})();

API Reference

identifyAudience(lat, lng, timestamp, options?) ⭐ RECOMMENDED

NEW in v1.2.0 - Auto-detects ZIP/postal codes worldwide!

Identifies audience segments for a single location and time with automatic geocoding.

Parameters:

  • lat (number): Latitude (-90 to 90) required
  • lng (number): Longitude (-180 to 180) required
  • timestamp (Date|string|number): When the action occurred required
  • options (Object, optional):
    • rideMode (string): 'work', 'watch', 'shop'
    • startZone (Object): Start zone for commuter logic
    • endZone (Object): End zone for commuter logic

Returns: Promise

{
  success: true,
  coordinates: { lat, lng, zipCode: "10000" },    // ← Auto-detected!
  geohashID: "dr5regw",                            // ← Auto-generated!
  timestamp: "2026-02-05T18:45:00Z",
  geoZones: [
    { id: "city-financial-districts", name: "City Financial Districts", ... }
  ],
  daypart: {
    id: "evening-peak",
    name: "Evening Peak",
    startTime: "16:00",
    endTime: "19:00"
  },
  audiences: [
    { id: "AUD-06", name: "Financial / Work / Business", tier: "Intent", ... }
  ],
  metadata: {
    isWeekday: true,
    queryTimeMs: 12,
    geohashPrecision: 7,
    version: "1.2.0"
  }
}

identifyAudienceWithZip(lat, lng, zipCode, timestamp, options?)

Legacy API - If you already have ZIP codes from another geocoding service.

Same as above but takes explicit zipCode parameter.

batchIdentifyAudiences(records)

Process multiple locations efficiently.

Parameters:

  • records (Array): Array of record objects, each with:
    {
      lat: 40.7128,
      lng: -74.0060,
      timestamp: '2026-02-05T18:45:00Z',
      options: { rideMode: 'work' }
    }

Returns: Promise - Aggregated statistics

🌍 NEW: reverseGeocodeWorldwide(lat, lng, timeout?)

NEW in v1.2.0 - Worldwide reverse geocoding with FREE Nominatim API

Converts any latitude/longitude on Earth to postal code, city, state, country.

Parameters:

  • lat (number): Latitude
  • lng (number): Longitude
  • timeout (number, optional): Request timeout in ms (default: 5000)

Returns: Promise

{
  city: "New York",
  postalCode: "10000",
  country: "United States",
  state: "New York",
  county: null,
  confidence: "high",
  source: "nominatim-worldwide"
}

Usage:

const { reverseGeocodeWorldwide } = require('@ivee/audience-identifier-core');

// Used automatically by identifyAudience(), but can also be used directly:
const geo = await reverseGeocodeWorldwide(51.5074, -0.1278); // London
// Returns: { postalCode: "WC2N 5DX", city: "City of Westminster", country: "United Kingdom" }

🆔 NEW: Geohash - Unique Geo IDs

NEW in v1.2.0 - Auto-generate unique location IDs

Generates deterministic geohash IDs (like "dr5regw") for spatial indexing and proximity search.

const {
  getGeohash,        // (lat, lng, precision) => "dr5regw"
  getGeohashInfo,    // Complete info with all details
  decodeGeohash,     // Reverse-convert hash to coordinates
  getGeohashNeighbors // Find 8 surrounding areas
} = require('@ivee/audience-identifier-core');

// Auto-generated in identifyAudience() response as "geohashID"
const result = await identifyAudience(40.7128, -74.0060, new Date());
console.log(result.geohashID);  // "dr5regw" ← Automatically generated!

// Direct usage:
const hash = getGeohash(40.7128, -74.0060, 7);
console.log(hash);  // "dr5regw" (~150m precision)

const info = getGeohashInfo(40.7128, -74.0060, 7);
console.log(info.neighbors);  // {north, south, east, west, ...}

Precision Levels:

  • Precision 1: ~5000 km (country level)
  • Precision 6: ~1.2 km (city level) ← Default
  • Precision 7: ~152m (neighborhood level)
  • Precision 8: ~38m (street level)
  • Precision 12: ~60cm (building level)

Utility Functions

const {
  classifyDaypart,        // (timestamp) => {id, name, startTime, endTime}
  isWeekday,              // (timestamp) => boolean
  detectGeoZonesByZip,    // (lat, lng, zipCode, options) => [zones]
  matchAudiences,         // (geoZones, daypart, options) => [audiences]
  reverseGeocode          // (lat, lng) => zone/city info (LOCAL fallback)
} = require('@ivee/audience-identifier-core');

Audience Segments (13 Total)

| ID | Name | Tier | Key Attributes | |----|------|------|---| | AUD-01 | Affluent Passengers | Demo/Psychographic | Luxury zones, daytime hours | | AUD-02 | Airport Travelers | Intent | Airport zones, all dayparts | | AUD-03 | Business Travelers | Intent | Hotels, conventions, business hours | | AUD-04 | Commuters | Intent | Home→Work/Workdays, peak hours | | AUD-05 | Experience Seekers | Interests | Entertainment venues, evenings | | AUD-06 | Financial/Work/Business | Intent | Business zones, workdays only | | AUD-07 | General DMA | Fallback | All zones, all times (catch-all) | | AUD-08 | Hungry Passengers | Purchase Intent | Restaurants, dining times | | AUD-09 | Entertainment Lovers | Interests | Cinema, nightlife, evenings | | AUD-10 | Night Out | Intent | Nightlife, late hours | | AUD-11 | Out of Towners | Intent | Airports, hotels, tourism | | AUD-12 | Retail Shoppers | Purchase Intent | Shopping districts, retail hours | | AUD-13 | Sports Enthusiasts | Interests | Sports venues, event hours |

Dayparts (6 Total)

| Name | Start | End | Use Case | |------|-------|-----|----------| | Early Morning | 05:00 | 09:00 | Commuting, early flights | | Midday | 09:00 | 16:00 | Workday, shopping, lunch | | Evening Peak | 16:00 | 19:00 | Post-work commute | | Prime Time | 19:00 | 23:00 | Entertainment, dining | | Late Night | 23:00 | 02:00 | Nightlife, late dining | | Overnight | 02:00 | 05:00 | Red-eyes, shift work |

Geographic Zones (15 Total)

Mapped across: NYC, Chicago, LA, Miami, Charlotte

  • Airport Zones
  • Hotel Zones
  • City Financial Districts
  • Office Hubs & Corporate Campuses
  • Major Retail Corridors & Shopping Districts
  • Restaurant & Food Districts
  • Nightlife Corridors
  • Cinema & Theater Zones
  • Stadium & Sports Venue Zones
  • Cultural & Museum Districts
  • Tourism & Visitor Zones
  • Affluent Residential Neighborhoods
  • General Residential Neighborhoods
  • And more...

ZIP Code / Postal Code Handling

✨ NEW: Automatic Detection (v1.2.0+)

You NO LONGER need external geocoding services!

The main identifyAudience() function now automatically detects postal codes worldwide:

const result = await identifyAudience(lat, lng, timestamp);
// ZIP/postal code is auto-detected! 
// Works for ANY location on Earth

Uses FREE Nominatim (OpenStreetMap) API - no API key required!

Legacy: Manual ZIP Code (Optional)

If you already have ZIP codes from another source, you can use the legacy function:

const { identifyAudienceWithZip } = require('@ivee/audience-identifier-core');

const result = await identifyAudienceWithZip(
  lat, lng, zipCode, timestamp, options
);

Getting ZIP Codes (if needed for legacy code):

For React Native:

For Node.js/Strapi:

Integrating with Strapi

1. Create a Custom Service

// api/audience/services/audience.js

module.exports = {
  async identifyAudience(lat, lng, timestamp) {
    const { identifyAudience } = 
      require('@mrazakassar/audience-identifier-core');
    
    // ZIP code is auto-detected worldwide!
    return await identifyAudience(lat, lng, timestamp);
  },

  async batchIdentify(records) {
    const { batchIdentifyAudiences } =
      require('@mrazakassar/audience-identifier-core');
    
    return await batchIdentifyAudiences(records);
  }
};

2. Create a POST Controller

// api/audience/controllers/audience.js

module.exports = {
  async identify(ctx) {
    const { lat, lng, timestamp } = ctx.request.body;
    
    // That's it! No ZIP code needed
    const result = await strapi
      .service('api::audience.audience')
      .identifyAudience(lat, lng, timestamp);
    
    ctx.body = result;
  }
};

3. Route Configuration

// api/audience/routes/audience.js

module.exports = {
  routes: [
    {
      method: 'POST',
      path: '/audience/identify',
      handler: 'audience.identify',
      config: { policies: [] }
    }
  ]
};

4. Test the API

curl -X POST http://localhost:1337/api/audience/identify \
  -H "Content-Type: application/json" \
  -d '{
    "lat": 40.7128,
    "lng": -74.0060,
    "timestamp": "2026-02-05T18:45:00Z"
  }'

Response:

{
  "success": true,
  "coordinates": {
    "lat": 40.7128,
    "lng": -74.0060,
    "zipCode": "10000"
  },
  "geohashID": "dr5regw",
  "daypart": {
    "name": "Evening Peak"
  },
  "audiences": [
    {
      "id": "AUD-06",
      "name": "Financial / Work / Business"
    }
  ]
}

Testing

# Run basic audience identification tests
npm test

# Run batch processing tests
npm run test:batch

# NEW: Test worldwide reverse geocoding (19 global locations)
npm run test:geocoding

# NEW: Test geohash generation
npm run test:geohash

# NEW: Test automatic geohash with real queries
npm run test:auto-geohash

Performance

  • Single Query: ~5-15ms
  • Batch (1000 records): ~10-20 seconds
  • Memory: <5MB for entire dataset
  • Caching: ZIP-to-zone lookups cached automatically

Troubleshooting

No audiences matched?

  • Ensure your ZIP code is correct
  • Check if ZIP code is supported (must be in supported cities)
  • Review the geoZones array - should not be empty

Wrong daypart returned?

  • Timestamps must be in valid ISO format or Date objects
  • Check timezone: internally uses UTC
  • Verify daypart times in exported dayparts array

Commuter audience not matching?

  • Requires requiresWeekday: true (Monday-Friday only)
  • Requires BOTH startZone and endZone
  • Start must be residential, end must be work zone
  • Must be during Early Morning (5-9 AM) or Evening Peak (4-7 PM)

License

MIT

Support

For issues, questions, or contributions, please visit: https://github.com/yourusername/audience-identifier-core


Version: 1.2.0
Last Updated: February 2026
Highlights: Worldwide reverse geocoding, auto geohash generation, zero-config setup