@adtogether/web-sdk 0.1.21 → 0.1.23
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/CHANGELOG.md +45 -42
- package/README.md +161 -154
- package/dist/{chunk-RW43ES42.mjs → chunk-IDISPRGA.mjs} +30 -1
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +30 -1
- package/dist/index.mjs +1 -1
- package/dist/react/index.js +30 -1
- package/dist/react/index.mjs +1 -1
- package/errors.txt +2 -2
- package/package.json +59 -59
- package/src/core/AdTogether.ts +32 -0
- package/src/react/AdTogetherInterstitial.tsx +370 -370
- package/tsconfig.json +19 -19
package/CHANGELOG.md
CHANGED
|
@@ -1,42 +1,45 @@
|
|
|
1
|
-
## 0.1.
|
|
2
|
-
|
|
3
|
-
* **
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
* **
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
1
|
+
## 0.1.23
|
|
2
|
+
|
|
3
|
+
* **Sync**: Version parity across all AdTogether SDKs.
|
|
4
|
+
|
|
5
|
+
## 0.1.22
|
|
6
|
+
* **Brand**: Added "Powered by AdTogether" attribution to all Interstitial ad formats.
|
|
7
|
+
* **Sync**: Unified versioning (0.1.20) across all AdTogether SDKs.
|
|
8
|
+
|
|
9
|
+
## 0.1.14
|
|
10
|
+
|
|
11
|
+
* **Feature**: Added `onAdClosed` callback support to banner components.
|
|
12
|
+
* **Feature**: Improved automatic `bundleId` detection across all platforms.
|
|
13
|
+
* **Security**: Hardened ad-serving logic to prevent payout fraud.
|
|
14
|
+
* **Sync**: Version parity across all AdTogether SDKs.
|
|
15
|
+
|
|
16
|
+
## 0.1.12
|
|
17
|
+
|
|
18
|
+
* **Feature**: Added `showCloseButton` to React components.
|
|
19
|
+
* **Standardization**: Support for `onAdLoaded` and `onAdFailedToLoad` across all platforms.
|
|
20
|
+
* **Layout**: Enhanced responsiveness and safety checks for ad rendering.
|
|
21
|
+
|
|
22
|
+
## 0.1.9
|
|
23
|
+
|
|
24
|
+
* **Feature**: Added `onAdLoaded` and `onAdFailedToLoad` callback support to React components.
|
|
25
|
+
* **Responsive**: Improved responsiveness for both Banner and Interstitial ad components.
|
|
26
|
+
* **Standardization**: Updated API signatures to match the unified AdTogether SDK standard.
|
|
27
|
+
|
|
28
|
+
## 0.1.7
|
|
29
|
+
|
|
30
|
+
* Documentation improvements.
|
|
31
|
+
* Localize ad assets for better registry rendering.
|
|
32
|
+
* Update Discord invite link to https://discord.gg/maA8g4ADpk.
|
|
33
|
+
|
|
34
|
+
## 0.1.4
|
|
35
|
+
|
|
36
|
+
* Update package metadata and dependencies.
|
|
37
|
+
|
|
38
|
+
## 0.1.1
|
|
39
|
+
|
|
40
|
+
* Update repository URLs to new organization.
|
|
41
|
+
* Prepare for version 0.1.1 release.
|
|
42
|
+
|
|
43
|
+
## 0.1.0
|
|
44
|
+
|
|
45
|
+
* Initial release of the AdTogether Web SDK.
|
package/README.md
CHANGED
|
@@ -1,154 +1,161 @@
|
|
|
1
|
-
# AdTogether Web SDK
|
|
2
|
-
|
|
3
|
-
[!
|
|
4
|
-
[
|
|
5
|
-
|
|
6
|
-
<p align="center">
|
|
7
|
-
<
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
|
90
|
-
|
|
91
|
-
| `
|
|
92
|
-
| `
|
|
93
|
-
| `
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
##
|
|
153
|
-
|
|
154
|
-
|
|
1
|
+
# AdTogether Web SDK
|
|
2
|
+
|
|
3
|
+
> [!IMPORTANT]
|
|
4
|
+
> **Developer Account Required**: Before integrating the SDK, you must create a developer account at [https://adtogether.relaxsoftwareapps.com](https://adtogether.relaxsoftwareapps.com) to generate your `appId` and configure your ad units. Integration will not work without a valid `appId`.
|
|
5
|
+
|
|
6
|
+
<p align="center">
|
|
7
|
+
<img src="../../public/dashboard.png" width="800" alt="Developer Dashboard">
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
[](https://www.npmjs.com/package/@adtogether/web-sdk)
|
|
11
|
+
[](https://opensource.org/licenses/MIT)
|
|
12
|
+
|
|
13
|
+
<p align="center">
|
|
14
|
+
<strong>"Show an ad, get an ad shown"</strong><br>
|
|
15
|
+
The Universal Ad Exchange & Reciprocal Marketing Platform
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
**AdTogether** is an ad exchange platform designed to empower developers and creators. By participating in our network, you can engage in reciprocal marketing for your own applications while simultaneously driving traffic to your products and helping you **increase conversions**. Our core philosophy is simple: **"Show an ad, get an ad shown"**.
|
|
21
|
+
|
|
22
|
+
This SDK allows web developers (React and Vanilla JS) to easily integrate AdTogether ads into their applications. By displaying ads from other community members, you earn **Ad Credits** that allow your own app's ads to be shown across the AdTogether network.
|
|
23
|
+
|
|
24
|
+
### 🖼️ Visualizing the Experience
|
|
25
|
+
|
|
26
|
+
| **Native Banner Ad** | **Interstitial Full-Screen** |
|
|
27
|
+
|:---:|:---:|
|
|
28
|
+
|  |  |
|
|
29
|
+
| *Adaptive React Banner Component* | *Full-Screen Interstitial Experience* |
|
|
30
|
+
|
|
31
|
+
## Features
|
|
32
|
+
|
|
33
|
+
- 🖼️ **Banner Ads** — Native React `AdTogetherBanner` component with automatic impression tracking and dark mode support.
|
|
34
|
+
- 📺 **Interstitial Ads** — Full-screen `AdTogetherInterstitial` component with a configurable close-button countdown.
|
|
35
|
+
- 🌑 **Dark Mode Support** — All ad components automatically adapt to system preference, or can be set to `'dark'` / `'light'` explicitly.
|
|
36
|
+
- ⚖️ **Fair Exchange** — Automated impression and click tracking ensures fair distribution of ad credits.
|
|
37
|
+
- 🔌 **Easy Integration** — A single `initialize()` call and one component is all you need to start earning credits and increase conversions.
|
|
38
|
+
- 🧩 **Vanilla JS Support** — Core logic decoupled for use without React or any framework.
|
|
39
|
+
|
|
40
|
+
## Getting Started
|
|
41
|
+
|
|
42
|
+
### 1. Install
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
npm install @adtogether/web-sdk
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 2. Initialize
|
|
49
|
+
|
|
50
|
+
Call `AdTogether.initialize()` before rendering any ad components. You can obtain your App ID from the [AdTogether Dashboard](https://adtogether.relaxsoftwareapps.com/dashboard).
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
import { AdTogether } from '@adtogether/web-sdk';
|
|
54
|
+
|
|
55
|
+
AdTogether.initialize({
|
|
56
|
+
appId: 'YOUR_APP_ID',
|
|
57
|
+
// bundleId: 'com.example.app' // optional: automatically detected from window.location.hostname
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
### Banner Ads
|
|
64
|
+
|
|
65
|
+
Use the `AdTogetherBanner` component anywhere in your React tree. It fetches an ad, renders it, and automatically tracks impressions when 50% or more of the component is visible.
|
|
66
|
+
|
|
67
|
+
```jsx
|
|
68
|
+
import { AdTogetherBanner } from '@adtogether/web-sdk/react';
|
|
69
|
+
|
|
70
|
+
function MyApp() {
|
|
71
|
+
return (
|
|
72
|
+
<div>
|
|
73
|
+
<h1>My Awesome Web App</h1>
|
|
74
|
+
|
|
75
|
+
<AdTogetherBanner
|
|
76
|
+
adUnitId="home_bottom_banner"
|
|
77
|
+
showCloseButton={true}
|
|
78
|
+
onAdLoaded={() => console.log('Banner loaded!')}
|
|
79
|
+
onAdFailedToLoad={(error) => console.error('Banner error:', error)}
|
|
80
|
+
onAdClosed={() => console.log('Banner closed!')}
|
|
81
|
+
/>
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
#### `AdTogetherBanner` Props
|
|
88
|
+
|
|
89
|
+
| Prop | Type | Default | Description |
|
|
90
|
+
|--------------------|-------------------------|-----------|-------------|
|
|
91
|
+
| `adUnitId` | `string` | **required** | Unique identifier for this ad placement. |
|
|
92
|
+
| `showCloseButton` | `boolean` | `false` | Show a dismissable close button overlay. |
|
|
93
|
+
| `onAdClosed` | `() => void` | — | Called when the user closes the ad. |
|
|
94
|
+
| `width` | `number \| string` | `'100%'` | Width of the ad element. |
|
|
95
|
+
| `height` | `number \| string` | `'auto'` | Height of the ad element. |
|
|
96
|
+
| `theme` | `'dark' \| 'light' \| 'auto'` | `'auto'` | Color scheme. `'auto'` follows system preference. |
|
|
97
|
+
| `onAdLoaded` | `() => void` | — | Called when the ad has been successfully fetched and rendered. |
|
|
98
|
+
| `onAdFailedToLoad` | `(error: Error) => void`| — | Called if the ad fails to load. |
|
|
99
|
+
| `className` | `string` | `''` | Additional CSS class name for the container. |
|
|
100
|
+
| `style` | `React.CSSProperties` | `{}` | Additional inline styles for the container. |
|
|
101
|
+
|
|
102
|
+
### Interstitial Ads
|
|
103
|
+
|
|
104
|
+
Show a full-screen interstitial ad as a portal overlay. A countdown timer is displayed before the user is allowed to close the ad.
|
|
105
|
+
|
|
106
|
+
```jsx
|
|
107
|
+
import { useState } from 'react';
|
|
108
|
+
import { AdTogetherInterstitial } from '@adtogether/web-sdk/react';
|
|
109
|
+
|
|
110
|
+
function MyApp() {
|
|
111
|
+
const [showInterstitial, setShowInterstitial] = useState(false);
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<div>
|
|
115
|
+
<button onClick={() => setShowInterstitial(true)}>
|
|
116
|
+
Show Interstitial Ad
|
|
117
|
+
</button>
|
|
118
|
+
|
|
119
|
+
<AdTogetherInterstitial
|
|
120
|
+
adUnitId="level_complete_interstitial"
|
|
121
|
+
isOpen={showInterstitial}
|
|
122
|
+
onClose={() => setShowInterstitial(false)}
|
|
123
|
+
closeDelay={5}
|
|
124
|
+
onAdLoaded={() => console.log('Interstitial ready')}
|
|
125
|
+
onAdFailedToLoad={(error) => console.error('Interstitial error:', error)}
|
|
126
|
+
/>
|
|
127
|
+
</div>
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
#### `AdTogetherInterstitial` Props
|
|
133
|
+
|
|
134
|
+
| Prop | Type | Default | Description |
|
|
135
|
+
|--------------------|-------------------------|-----------|-------------|
|
|
136
|
+
| `adUnitId` | `string` | **required** | Unique identifier for this ad placement. |
|
|
137
|
+
| `isOpen` | `boolean` | **required** | When `true`, the interstitial is displayed. |
|
|
138
|
+
| `onClose` | `() => void` | **required** | Called when the user closes the interstitial. |
|
|
139
|
+
| `closeDelay` | `number` | `3` | Seconds before the close button appears. A countdown is shown during this time. |
|
|
140
|
+
| `theme` | `'dark' \| 'light' \| 'auto'` | `'auto'` | Color scheme. `'auto'` follows system preference. |
|
|
141
|
+
| `onAdLoaded` | `() => void` | — | Called when the ad has been successfully fetched. |
|
|
142
|
+
| `onAdFailedToLoad` | `(error: Error) => void`| — | Called if the ad fails to load. The dialog is automatically dismissed on failure. |
|
|
143
|
+
|
|
144
|
+
## How Credits Work
|
|
145
|
+
|
|
146
|
+
1. **Earn credits** — Every time your app displays an ad from the AdTogether network and the impression is verified, you earn ad credits.
|
|
147
|
+
2. **Spend credits** — Your ad credits are automatically spent to show *your* campaigns inside other apps on the network, helping you increase conversions.
|
|
148
|
+
3. **Fair weighting** — Different ad formats and geographies have different credit weights, ensuring a level playing field for apps of all sizes.
|
|
149
|
+
|
|
150
|
+
Create and manage your campaigns from the [AdTogether Dashboard](https://adtogether.relaxsoftwareapps.com/dashboard).
|
|
151
|
+
|
|
152
|
+
## Additional Information
|
|
153
|
+
|
|
154
|
+
- 📖 **Documentation**: [adtogether.relaxsoftwareapps.com/docs](https://adtogether.relaxsoftwareapps.com/docs)
|
|
155
|
+
- 🐛 **Issues**: [GitHub Issues](https://github.com/undecided2003/AdTogether/issues)
|
|
156
|
+
- 💬 **Support**: Join our [Discord community](https://discord.gg/maA8g4ADpk) for real-time help.
|
|
157
|
+
- 🌐 **Dashboard**: [adtogether.relaxsoftwareapps.com/dashboard](https://adtogether.relaxsoftwareapps.com/dashboard)
|
|
158
|
+
|
|
159
|
+
## License
|
|
160
|
+
|
|
161
|
+
This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
|
|
@@ -72,6 +72,34 @@ var AdTogether = class _AdTogether {
|
|
|
72
72
|
static trackClick(adId, token) {
|
|
73
73
|
this.trackEvent("/api/ads/click", adId, token);
|
|
74
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* Detect the user's country code from the browser locale.
|
|
77
|
+
* Uses Intl API (most reliable) with navigator.language as fallback.
|
|
78
|
+
* Returns an ISO 3166-1 alpha-2 code like "US", "DE", "JP", or null.
|
|
79
|
+
*/
|
|
80
|
+
static detectCountry() {
|
|
81
|
+
try {
|
|
82
|
+
if (typeof Intl !== "undefined" && Intl.DateTimeFormat) {
|
|
83
|
+
const resolved = Intl.DateTimeFormat().resolvedOptions();
|
|
84
|
+
if (resolved.locale) {
|
|
85
|
+
const parts = resolved.locale.split("-");
|
|
86
|
+
if (parts.length >= 2) {
|
|
87
|
+
const region = parts[parts.length - 1].toUpperCase();
|
|
88
|
+
if (region.length === 2) return region;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
if (typeof navigator !== "undefined" && navigator.language) {
|
|
93
|
+
const parts = navigator.language.split("-");
|
|
94
|
+
if (parts.length >= 2) {
|
|
95
|
+
const region = parts[parts.length - 1].toUpperCase();
|
|
96
|
+
if (region.length === 2) return region;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} catch (_) {
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
75
103
|
static trackEvent(endpoint, adId, token) {
|
|
76
104
|
if (!_AdTogether.shared.assertInitialized()) return;
|
|
77
105
|
fetch(`${_AdTogether.shared.baseUrl}${endpoint}`, {
|
|
@@ -86,7 +114,8 @@ var AdTogether = class _AdTogether {
|
|
|
86
114
|
..._AdTogether.shared.bundleId ? { bundleId: _AdTogether.shared.bundleId } : {},
|
|
87
115
|
// Send platform and environment to match Flutter SDK
|
|
88
116
|
platform: "web",
|
|
89
|
-
environment: typeof process !== "undefined" && process.env?.NODE_ENV === "development" ? "development" : "production"
|
|
117
|
+
environment: typeof process !== "undefined" && process.env?.NODE_ENV === "development" ? "development" : "production",
|
|
118
|
+
country: _AdTogether.detectCountry()
|
|
90
119
|
})
|
|
91
120
|
}).catch(console.error);
|
|
92
121
|
}
|
package/dist/index.d.mts
CHANGED
|
@@ -31,6 +31,12 @@ declare class AdTogether {
|
|
|
31
31
|
static fetchAd(adUnitId: string, adType?: AdType): Promise<AdModel>;
|
|
32
32
|
static trackImpression(adId: string, token?: string): void;
|
|
33
33
|
static trackClick(adId: string, token?: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Detect the user's country code from the browser locale.
|
|
36
|
+
* Uses Intl API (most reliable) with navigator.language as fallback.
|
|
37
|
+
* Returns an ISO 3166-1 alpha-2 code like "US", "DE", "JP", or null.
|
|
38
|
+
*/
|
|
39
|
+
private static detectCountry;
|
|
34
40
|
private static trackEvent;
|
|
35
41
|
}
|
|
36
42
|
|
package/dist/index.d.ts
CHANGED
|
@@ -31,6 +31,12 @@ declare class AdTogether {
|
|
|
31
31
|
static fetchAd(adUnitId: string, adType?: AdType): Promise<AdModel>;
|
|
32
32
|
static trackImpression(adId: string, token?: string): void;
|
|
33
33
|
static trackClick(adId: string, token?: string): void;
|
|
34
|
+
/**
|
|
35
|
+
* Detect the user's country code from the browser locale.
|
|
36
|
+
* Uses Intl API (most reliable) with navigator.language as fallback.
|
|
37
|
+
* Returns an ISO 3166-1 alpha-2 code like "US", "DE", "JP", or null.
|
|
38
|
+
*/
|
|
39
|
+
private static detectCountry;
|
|
34
40
|
private static trackEvent;
|
|
35
41
|
}
|
|
36
42
|
|
package/dist/index.js
CHANGED
|
@@ -98,6 +98,34 @@ var AdTogether = class _AdTogether {
|
|
|
98
98
|
static trackClick(adId, token) {
|
|
99
99
|
this.trackEvent("/api/ads/click", adId, token);
|
|
100
100
|
}
|
|
101
|
+
/**
|
|
102
|
+
* Detect the user's country code from the browser locale.
|
|
103
|
+
* Uses Intl API (most reliable) with navigator.language as fallback.
|
|
104
|
+
* Returns an ISO 3166-1 alpha-2 code like "US", "DE", "JP", or null.
|
|
105
|
+
*/
|
|
106
|
+
static detectCountry() {
|
|
107
|
+
try {
|
|
108
|
+
if (typeof Intl !== "undefined" && Intl.DateTimeFormat) {
|
|
109
|
+
const resolved = Intl.DateTimeFormat().resolvedOptions();
|
|
110
|
+
if (resolved.locale) {
|
|
111
|
+
const parts = resolved.locale.split("-");
|
|
112
|
+
if (parts.length >= 2) {
|
|
113
|
+
const region = parts[parts.length - 1].toUpperCase();
|
|
114
|
+
if (region.length === 2) return region;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (typeof navigator !== "undefined" && navigator.language) {
|
|
119
|
+
const parts = navigator.language.split("-");
|
|
120
|
+
if (parts.length >= 2) {
|
|
121
|
+
const region = parts[parts.length - 1].toUpperCase();
|
|
122
|
+
if (region.length === 2) return region;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
} catch (_) {
|
|
126
|
+
}
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
101
129
|
static trackEvent(endpoint, adId, token) {
|
|
102
130
|
if (!_AdTogether.shared.assertInitialized()) return;
|
|
103
131
|
fetch(`${_AdTogether.shared.baseUrl}${endpoint}`, {
|
|
@@ -112,7 +140,8 @@ var AdTogether = class _AdTogether {
|
|
|
112
140
|
..._AdTogether.shared.bundleId ? { bundleId: _AdTogether.shared.bundleId } : {},
|
|
113
141
|
// Send platform and environment to match Flutter SDK
|
|
114
142
|
platform: "web",
|
|
115
|
-
environment: typeof process !== "undefined" && process.env?.NODE_ENV === "development" ? "development" : "production"
|
|
143
|
+
environment: typeof process !== "undefined" && process.env?.NODE_ENV === "development" ? "development" : "production",
|
|
144
|
+
country: _AdTogether.detectCountry()
|
|
116
145
|
})
|
|
117
146
|
}).catch(console.error);
|
|
118
147
|
}
|
package/dist/index.mjs
CHANGED
package/dist/react/index.js
CHANGED
|
@@ -102,6 +102,34 @@ var AdTogether = class _AdTogether {
|
|
|
102
102
|
static trackClick(adId, token) {
|
|
103
103
|
this.trackEvent("/api/ads/click", adId, token);
|
|
104
104
|
}
|
|
105
|
+
/**
|
|
106
|
+
* Detect the user's country code from the browser locale.
|
|
107
|
+
* Uses Intl API (most reliable) with navigator.language as fallback.
|
|
108
|
+
* Returns an ISO 3166-1 alpha-2 code like "US", "DE", "JP", or null.
|
|
109
|
+
*/
|
|
110
|
+
static detectCountry() {
|
|
111
|
+
try {
|
|
112
|
+
if (typeof Intl !== "undefined" && Intl.DateTimeFormat) {
|
|
113
|
+
const resolved = Intl.DateTimeFormat().resolvedOptions();
|
|
114
|
+
if (resolved.locale) {
|
|
115
|
+
const parts = resolved.locale.split("-");
|
|
116
|
+
if (parts.length >= 2) {
|
|
117
|
+
const region = parts[parts.length - 1].toUpperCase();
|
|
118
|
+
if (region.length === 2) return region;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (typeof navigator !== "undefined" && navigator.language) {
|
|
123
|
+
const parts = navigator.language.split("-");
|
|
124
|
+
if (parts.length >= 2) {
|
|
125
|
+
const region = parts[parts.length - 1].toUpperCase();
|
|
126
|
+
if (region.length === 2) return region;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
} catch (_) {
|
|
130
|
+
}
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
105
133
|
static trackEvent(endpoint, adId, token) {
|
|
106
134
|
if (!_AdTogether.shared.assertInitialized()) return;
|
|
107
135
|
fetch(`${_AdTogether.shared.baseUrl}${endpoint}`, {
|
|
@@ -116,7 +144,8 @@ var AdTogether = class _AdTogether {
|
|
|
116
144
|
..._AdTogether.shared.bundleId ? { bundleId: _AdTogether.shared.bundleId } : {},
|
|
117
145
|
// Send platform and environment to match Flutter SDK
|
|
118
146
|
platform: "web",
|
|
119
|
-
environment: typeof process !== "undefined" && process.env?.NODE_ENV === "development" ? "development" : "production"
|
|
147
|
+
environment: typeof process !== "undefined" && process.env?.NODE_ENV === "development" ? "development" : "production",
|
|
148
|
+
country: _AdTogether.detectCountry()
|
|
120
149
|
})
|
|
121
150
|
}).catch(console.error);
|
|
122
151
|
}
|
package/dist/react/index.mjs
CHANGED
package/errors.txt
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
tsconfig.json(15,25): error TS5107: Option 'moduleResolution=node10' is deprecated and will stop functioning in TypeScript 7.0. Specify compilerOption '"ignoreDeprecations": "6.0"' to silence this error.
|
|
2
|
-
Visit https://aka.ms/ts6 for migration information.
|
|
1
|
+
tsconfig.json(15,25): error TS5107: Option 'moduleResolution=node10' is deprecated and will stop functioning in TypeScript 7.0. Specify compilerOption '"ignoreDeprecations": "6.0"' to silence this error.
|
|
2
|
+
Visit https://aka.ms/ts6 for migration information.
|