user-analytics-tracker 4.3.0 → 4.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -137,6 +137,7 @@ interface AnalyticsConfig {
137
137
  apiKey?: string;
138
138
  baseUrl?: string;
139
139
  timeout?: number;
140
+ ip?: string;
140
141
  };
141
142
  fieldStorage?: {
142
143
  ipLocation?: FieldStorageConfig$1;
@@ -254,22 +255,28 @@ declare class DeviceDetector {
254
255
  *
255
256
  * 1) Browser / client-side:
256
257
  * - Do NOT pass an IP. Call getCompleteIPLocation(config) with no IP.
257
- * - The request goes: user's browser → ipwho.is; ipwho.is sees the visitor's
258
- * public IP and returns it. The IP is never stored or sent by your code.
259
- * - For config.apiKey: avoid hardcoding. Use a build-time env var or omit (free tier).
258
+ * - The request goes: user's browser → API; the API sees the visitor's IP and returns it.
259
+ * - For config.apiKey: use env var or omit (free tier).
260
260
  *
261
261
  * 2) Server-side (Node/Express/Next etc.):
262
- * - Get the visitor's IP from the incoming request with getIPFromRequest(req).
263
- * - Then call getIPLocation(userIp, config) to geolocate that IP.
264
- * - Keep apiKey in process.env (e.g. IPWHOIS_API_KEY); never commit it.
262
+ * - Get the visitor's IP with getIPFromRequest(req), then call getIPLocation(userIp, config).
263
+ * - Or pass ip + apiKey in config: getCompleteIPLocation({ baseUrl, apiKey, ip: userIp }).
264
+ * - Keep apiKey in process.env; never commit it.
265
+ *
266
+ * 3) Paid subscription (e.g. ipwhois.pro):
267
+ * - URL format: https://ipwhois.pro/{IP}?key=YOUR_API_KEY
268
+ * - Pass baseUrl: 'https://ipwhois.pro', apiKey, and ip when you have the IP.
265
269
  */
266
270
  /**
267
271
  * IP Geolocation configuration interface
272
+ * Supports ipwho.is (free/paid) and ipwhois.pro (paid: baseUrl/{IP}?key=API_KEY)
268
273
  */
269
274
  interface IPGeolocationConfig {
270
275
  apiKey?: string;
271
276
  baseUrl?: string;
272
277
  timeout?: number;
278
+ /** When provided (e.g. server-side or paid flow), lookup this IP. URL becomes baseUrl/{ip}?key=API_KEY */
279
+ ip?: string;
273
280
  }
274
281
  /**
275
282
  * Get complete IP location data from ipwho.is API (HIGH PRIORITY)
@@ -280,13 +287,17 @@ interface IPGeolocationConfig {
280
287
  *
281
288
  * @example
282
289
  * ```typescript
283
- * // Without API key (free tier)
290
+ * // Without API key (free tier) - auto-detect requestor IP
284
291
  * const location = await getCompleteIPLocation();
285
292
  *
286
- * // With API key (for higher rate limits)
293
+ * // With API key (higher rate limits)
294
+ * const location = await getCompleteIPLocation({ apiKey: '<key>', baseUrl: 'https://ipwho.is' });
295
+ *
296
+ * // Paid / server-side: provide IP + API key (e.g. ipwhois.pro)
287
297
  * const location = await getCompleteIPLocation({
288
- * apiKey: '<your-api-key>',
289
- * baseUrl: 'https://ipwho.is'
298
+ * baseUrl: 'https://ipwhois.pro',
299
+ * apiKey: '<key>',
300
+ * ip: '203.0.113.42',
290
301
  * });
291
302
  * ```
292
303
  */
@@ -322,8 +333,12 @@ declare function getPublicIP(config?: IPGeolocationConfig): Promise<string | nul
322
333
  * const location = await getIPLocation('203.0.113.42');
323
334
  *
324
335
  * // With API key
336
+ * const location = await getIPLocation('203.0.113.42', { apiKey: '<key>' });
337
+ *
338
+ * // Paid ipwhois.pro: same URL format baseUrl/{IP}?key=API_KEY
325
339
  * const location = await getIPLocation('203.0.113.42', {
326
- * apiKey: '<your-api-key>'
340
+ * baseUrl: 'https://ipwhois.pro',
341
+ * apiKey: '<key>',
327
342
  * });
328
343
  * ```
329
344
  *
package/dist/index.d.ts CHANGED
@@ -137,6 +137,7 @@ interface AnalyticsConfig {
137
137
  apiKey?: string;
138
138
  baseUrl?: string;
139
139
  timeout?: number;
140
+ ip?: string;
140
141
  };
141
142
  fieldStorage?: {
142
143
  ipLocation?: FieldStorageConfig$1;
@@ -254,22 +255,28 @@ declare class DeviceDetector {
254
255
  *
255
256
  * 1) Browser / client-side:
256
257
  * - Do NOT pass an IP. Call getCompleteIPLocation(config) with no IP.
257
- * - The request goes: user's browser → ipwho.is; ipwho.is sees the visitor's
258
- * public IP and returns it. The IP is never stored or sent by your code.
259
- * - For config.apiKey: avoid hardcoding. Use a build-time env var or omit (free tier).
258
+ * - The request goes: user's browser → API; the API sees the visitor's IP and returns it.
259
+ * - For config.apiKey: use env var or omit (free tier).
260
260
  *
261
261
  * 2) Server-side (Node/Express/Next etc.):
262
- * - Get the visitor's IP from the incoming request with getIPFromRequest(req).
263
- * - Then call getIPLocation(userIp, config) to geolocate that IP.
264
- * - Keep apiKey in process.env (e.g. IPWHOIS_API_KEY); never commit it.
262
+ * - Get the visitor's IP with getIPFromRequest(req), then call getIPLocation(userIp, config).
263
+ * - Or pass ip + apiKey in config: getCompleteIPLocation({ baseUrl, apiKey, ip: userIp }).
264
+ * - Keep apiKey in process.env; never commit it.
265
+ *
266
+ * 3) Paid subscription (e.g. ipwhois.pro):
267
+ * - URL format: https://ipwhois.pro/{IP}?key=YOUR_API_KEY
268
+ * - Pass baseUrl: 'https://ipwhois.pro', apiKey, and ip when you have the IP.
265
269
  */
266
270
  /**
267
271
  * IP Geolocation configuration interface
272
+ * Supports ipwho.is (free/paid) and ipwhois.pro (paid: baseUrl/{IP}?key=API_KEY)
268
273
  */
269
274
  interface IPGeolocationConfig {
270
275
  apiKey?: string;
271
276
  baseUrl?: string;
272
277
  timeout?: number;
278
+ /** When provided (e.g. server-side or paid flow), lookup this IP. URL becomes baseUrl/{ip}?key=API_KEY */
279
+ ip?: string;
273
280
  }
274
281
  /**
275
282
  * Get complete IP location data from ipwho.is API (HIGH PRIORITY)
@@ -280,13 +287,17 @@ interface IPGeolocationConfig {
280
287
  *
281
288
  * @example
282
289
  * ```typescript
283
- * // Without API key (free tier)
290
+ * // Without API key (free tier) - auto-detect requestor IP
284
291
  * const location = await getCompleteIPLocation();
285
292
  *
286
- * // With API key (for higher rate limits)
293
+ * // With API key (higher rate limits)
294
+ * const location = await getCompleteIPLocation({ apiKey: '<key>', baseUrl: 'https://ipwho.is' });
295
+ *
296
+ * // Paid / server-side: provide IP + API key (e.g. ipwhois.pro)
287
297
  * const location = await getCompleteIPLocation({
288
- * apiKey: '<your-api-key>',
289
- * baseUrl: 'https://ipwho.is'
298
+ * baseUrl: 'https://ipwhois.pro',
299
+ * apiKey: '<key>',
300
+ * ip: '203.0.113.42',
290
301
  * });
291
302
  * ```
292
303
  */
@@ -322,8 +333,12 @@ declare function getPublicIP(config?: IPGeolocationConfig): Promise<string | nul
322
333
  * const location = await getIPLocation('203.0.113.42');
323
334
  *
324
335
  * // With API key
336
+ * const location = await getIPLocation('203.0.113.42', { apiKey: '<key>' });
337
+ *
338
+ * // Paid ipwhois.pro: same URL format baseUrl/{IP}?key=API_KEY
325
339
  * const location = await getIPLocation('203.0.113.42', {
326
- * apiKey: '<your-api-key>'
340
+ * baseUrl: 'https://ipwhois.pro',
341
+ * apiKey: '<key>',
327
342
  * });
328
343
  * ```
329
344
  *
package/dist/index.esm.js CHANGED
@@ -621,13 +621,17 @@ function checkAndSetLocationConsent(msisdn) {
621
621
  *
622
622
  * @example
623
623
  * ```typescript
624
- * // Without API key (free tier)
624
+ * // Without API key (free tier) - auto-detect requestor IP
625
625
  * const location = await getCompleteIPLocation();
626
626
  *
627
- * // With API key (for higher rate limits)
627
+ * // With API key (higher rate limits)
628
+ * const location = await getCompleteIPLocation({ apiKey: '<key>', baseUrl: 'https://ipwho.is' });
629
+ *
630
+ * // Paid / server-side: provide IP + API key (e.g. ipwhois.pro)
628
631
  * const location = await getCompleteIPLocation({
629
- * apiKey: '<your-api-key>',
630
- * baseUrl: 'https://ipwho.is'
632
+ * baseUrl: 'https://ipwhois.pro',
633
+ * apiKey: '<key>',
634
+ * ip: '203.0.113.42',
631
635
  * });
632
636
  * ```
633
637
  */
@@ -640,17 +644,25 @@ async function getCompleteIPLocation(config) {
640
644
  const baseUrl = config?.baseUrl || 'https://ipwho.is';
641
645
  const timeout = config?.timeout || 5000;
642
646
  const apiKey = config?.apiKey;
647
+ const configIp = config?.ip?.trim();
643
648
  try {
644
- // Build URL with optional API key
649
+ // Build URL: baseUrl/{IP}?key=API_KEY when IP provided (paid/server-side); else baseUrl/ or baseUrl?key=...
645
650
  let url = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
646
- // Add API key as query parameter if provided
647
- if (apiKey) {
648
- url += `?key=${encodeURIComponent(apiKey)}`;
651
+ if (configIp) {
652
+ // Paid / server-side: lookup specific IP. Format: https://ipwhois.pro/{IP}?key=YOUR_API_KEY
653
+ url += `/${encodeURIComponent(configIp)}`;
654
+ if (apiKey) {
655
+ url += `?key=${encodeURIComponent(apiKey)}`;
656
+ }
649
657
  }
650
658
  else {
659
+ // Auto-detect requestor IP (root path + optional key)
651
660
  url += '/';
661
+ if (apiKey) {
662
+ url += `?key=${encodeURIComponent(apiKey)}`;
663
+ }
652
664
  }
653
- // Call ipwho.is without IP parameter - it auto-detects user's IP and returns everything
665
+ // Call API: with IP path it returns that IP's location; without path it returns requestor's IP
654
666
  // This is the HIGH PRIORITY source - gets IP, location, connection, timezone, flag, etc. in one call
655
667
  const response = await fetch(url, {
656
668
  method: 'GET',
@@ -730,6 +742,10 @@ async function getCompleteIPLocation(config) {
730
742
  * ```
731
743
  */
732
744
  async function getPublicIP(config) {
745
+ // When consumer provides IP (paid/server-side), return it without fetching
746
+ if (config?.ip?.trim()) {
747
+ return config.ip.trim();
748
+ }
733
749
  // Try to get complete location first (includes IP)
734
750
  const completeLocation = await getCompleteIPLocation(config);
735
751
  if (completeLocation?.ip) {
@@ -740,7 +756,7 @@ async function getPublicIP(config) {
740
756
  const baseUrl = config?.baseUrl || 'https://ipwho.is';
741
757
  const timeout = config?.timeout || 5000;
742
758
  const apiKey = config?.apiKey;
743
- // Build URL with optional API key
759
+ // Build URL with optional API key (auto-detect requestor IP)
744
760
  let url = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
745
761
  if (apiKey) {
746
762
  url += `?key=${encodeURIComponent(apiKey)}`;
@@ -787,8 +803,12 @@ async function getPublicIP(config) {
787
803
  * const location = await getIPLocation('203.0.113.42');
788
804
  *
789
805
  * // With API key
806
+ * const location = await getIPLocation('203.0.113.42', { apiKey: '<key>' });
807
+ *
808
+ * // Paid ipwhois.pro: same URL format baseUrl/{IP}?key=API_KEY
790
809
  * const location = await getIPLocation('203.0.113.42', {
791
- * apiKey: '<your-api-key>'
810
+ * baseUrl: 'https://ipwhois.pro',
811
+ * apiKey: '<key>',
792
812
  * });
793
813
  * ```
794
814
  *
@@ -812,14 +832,13 @@ async function getIPLocation(ip, config) {
812
832
  const baseUrl = config?.baseUrl || 'https://ipwho.is';
813
833
  const timeout = config?.timeout || 5000;
814
834
  const apiKey = config?.apiKey;
815
- // Build URL with IP and optional API key
835
+ // Build URL: baseUrl/{IP}?key=API_KEY (same format as ipwhois.pro paid: https://ipwhois.pro/{IP}?key=YOUR_API_KEY)
816
836
  let url = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
817
- url += `/${ip}`;
818
- // Add API key as query parameter if provided
837
+ url += `/${encodeURIComponent(ip)}`;
819
838
  if (apiKey) {
820
839
  url += `?key=${encodeURIComponent(apiKey)}`;
821
840
  }
822
- // Using ipwho.is API
841
+ // Using ipwho.is / ipwhois.pro API
823
842
  const response = await fetch(url, {
824
843
  method: 'GET',
825
844
  headers: {