@adtogether/web-sdk 0.1.0 → 0.1.4

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 CHANGED
@@ -1,3 +1,8 @@
1
+ ## 0.1.1
2
+
3
+ * Update repository URLs to new organization.
4
+ * Prepare for version 0.1.1 release.
5
+
1
6
  ## 0.1.0
2
7
 
3
8
  * Initial release of the AdTogether Web SDK.
package/README.md ADDED
@@ -0,0 +1,147 @@
1
+ # AdTogether Web SDK
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@adtogether/web-sdk)](https://www.npmjs.com/package/@adtogether/web-sdk)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ <p align="center">
7
+ <strong>"Show an ad, get an ad shown"</strong><br>
8
+ The Universal Ad Exchange & Reciprocal Marketing Platform
9
+ </p>
10
+
11
+ ---
12
+
13
+ **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"**.
14
+
15
+ 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.
16
+
17
+ ### 🖼️ Visualizing the Experience
18
+
19
+ | **Native Banner Ad** | **Interstitial Full-Screen** |
20
+ |:---:|:---:|
21
+ | ![Banner Example](../../public/ads/Banner_Example.png) | ![Interstitial Example](../../public/ads/Interstitial_Example.png) |
22
+ | *Adaptive React Banner Component* | *Full-Screen Interstitial Experience* |
23
+
24
+ ## Features
25
+
26
+ - 🖼️ **Banner Ads** — Native React `AdTogetherBanner` component with automatic impression tracking and dark mode support.
27
+ - 📺 **Interstitial Ads** — Full-screen `AdTogetherInterstitial` component with a configurable close-button countdown.
28
+ - 🌑 **Dark Mode Support** — All ad components automatically adapt to system preference, or can be set to `'dark'` / `'light'` explicitly.
29
+ - ⚖️ **Fair Exchange** — Automated impression and click tracking ensures fair distribution of ad credits.
30
+ - 🔌 **Easy Integration** — A single `initialize()` call and one component is all you need to start earning credits and increase conversions.
31
+ - 🧩 **Vanilla JS Support** — Core logic decoupled for use without React or any framework.
32
+
33
+ ## Getting Started
34
+
35
+ ### 1. Install
36
+
37
+ ```bash
38
+ npm install @adtogether/web-sdk
39
+ ```
40
+
41
+ ### 2. Initialize
42
+
43
+ Call `AdTogether.initialize()` before rendering any ad components. You can obtain your App ID from the [AdTogether Dashboard](https://adtogether.relaxsoftwareapps.com/dashboard).
44
+
45
+ ```typescript
46
+ import { AdTogether } from '@adtogether/web-sdk';
47
+
48
+ AdTogether.initialize({ appId: 'YOUR_APP_ID' });
49
+ ```
50
+
51
+ ## Usage
52
+
53
+ ### Banner Ads
54
+
55
+ 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.
56
+
57
+ ```jsx
58
+ import { AdTogetherBanner } from '@adtogether/web-sdk/react';
59
+
60
+ function MyApp() {
61
+ return (
62
+ <div>
63
+ <h1>My Awesome Web App</h1>
64
+
65
+ <AdTogetherBanner
66
+ adUnitId="home_bottom_banner"
67
+ onAdLoaded={() => console.log('Banner loaded!')}
68
+ onAdFailedToLoad={(error) => console.error('Banner error:', error)}
69
+ />
70
+ </div>
71
+ );
72
+ }
73
+ ```
74
+
75
+ #### `AdTogetherBanner` Props
76
+
77
+ | Prop | Type | Default | Description |
78
+ |--------------------|-------------------------|-----------|-------------|
79
+ | `adUnitId` | `string` | **required** | Unique identifier for this ad placement. |
80
+ | `width` | `number \| string` | `'100%'` | Width of the ad element. |
81
+ | `height` | `number \| string` | `'auto'` | Height of the ad element. |
82
+ | `theme` | `'dark' \| 'light' \| 'auto'` | `'auto'` | Color scheme. `'auto'` follows system preference. |
83
+ | `onAdLoaded` | `() => void` | — | Called when the ad has been successfully fetched and rendered. |
84
+ | `onAdFailedToLoad` | `(error: Error) => void`| — | Called if the ad fails to load. |
85
+ | `className` | `string` | `''` | Additional CSS class name for the container. |
86
+ | `style` | `React.CSSProperties` | `{}` | Additional inline styles for the container. |
87
+
88
+ ### Interstitial Ads
89
+
90
+ Show a full-screen interstitial ad as a portal overlay. A countdown timer is displayed before the user is allowed to close the ad.
91
+
92
+ ```jsx
93
+ import { useState } from 'react';
94
+ import { AdTogetherInterstitial } from '@adtogether/web-sdk/react';
95
+
96
+ function MyApp() {
97
+ const [showInterstitial, setShowInterstitial] = useState(false);
98
+
99
+ return (
100
+ <div>
101
+ <button onClick={() => setShowInterstitial(true)}>
102
+ Show Interstitial Ad
103
+ </button>
104
+
105
+ <AdTogetherInterstitial
106
+ adUnitId="level_complete_interstitial"
107
+ isOpen={showInterstitial}
108
+ onClose={() => setShowInterstitial(false)}
109
+ closeDelay={5}
110
+ onAdLoaded={() => console.log('Interstitial ready')}
111
+ onAdFailedToLoad={(error) => console.error('Interstitial error:', error)}
112
+ />
113
+ </div>
114
+ );
115
+ }
116
+ ```
117
+
118
+ #### `AdTogetherInterstitial` Props
119
+
120
+ | Prop | Type | Default | Description |
121
+ |--------------------|-------------------------|-----------|-------------|
122
+ | `adUnitId` | `string` | **required** | Unique identifier for this ad placement. |
123
+ | `isOpen` | `boolean` | **required** | When `true`, the interstitial is displayed. |
124
+ | `onClose` | `() => void` | **required** | Called when the user closes the interstitial. |
125
+ | `closeDelay` | `number` | `3` | Seconds before the close button appears. A countdown is shown during this time. |
126
+ | `theme` | `'dark' \| 'light' \| 'auto'` | `'auto'` | Color scheme. `'auto'` follows system preference. |
127
+ | `onAdLoaded` | `() => void` | — | Called when the ad has been successfully fetched. |
128
+ | `onAdFailedToLoad` | `(error: Error) => void`| — | Called if the ad fails to load. The dialog is automatically dismissed on failure. |
129
+
130
+ ## How Credits Work
131
+
132
+ 1. **Earn credits** — Every time your app displays an ad from the AdTogether network and the impression is verified, you earn ad credits.
133
+ 2. **Spend credits** — Your ad credits are automatically spent to show *your* campaigns inside other apps on the network, helping you increase conversions.
134
+ 3. **Fair weighting** — Different ad formats and geographies have different credit weights, ensuring a level playing field for apps of all sizes.
135
+
136
+ Create and manage your campaigns from the [AdTogether Dashboard](https://adtogether.relaxsoftwareapps.com/dashboard).
137
+
138
+ ## Additional Information
139
+
140
+ - 📖 **Documentation**: [adtogether.relaxsoftwareapps.com/docs](https://adtogether.relaxsoftwareapps.com/docs)
141
+ - 🐛 **Issues**: [GitHub Issues](https://github.com/undecided2003/AdTogether/issues)
142
+ - 💬 **Support**: Join our [Discord community](https://discord.gg/adtogether) for real-time help.
143
+ - 🌐 **Dashboard**: [adtogether.relaxsoftwareapps.com/dashboard](https://adtogether.relaxsoftwareapps.com/dashboard)
144
+
145
+ ## License
146
+
147
+ This project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,85 @@
1
+ // src/core/AdTogether.ts
2
+ var AdTogether = class _AdTogether {
3
+ constructor() {
4
+ this.allowSelfAds = true;
5
+ this.baseUrl = "https://adtogether.relaxsoftwareapps.com";
6
+ }
7
+ static get shared() {
8
+ if (!_AdTogether.instance) {
9
+ _AdTogether.instance = new _AdTogether();
10
+ }
11
+ return _AdTogether.instance;
12
+ }
13
+ static initialize(options) {
14
+ const sdk = _AdTogether.shared;
15
+ sdk.appId = options.apiKey || options.appId;
16
+ if (options.allowSelfAds !== void 0) {
17
+ sdk.allowSelfAds = options.allowSelfAds;
18
+ }
19
+ if (options.baseUrl) {
20
+ sdk.baseUrl = options.baseUrl;
21
+ } else if (typeof window !== "undefined") {
22
+ sdk.baseUrl = "";
23
+ }
24
+ console.log(`AdTogether SDK Initialized with App ID: ${sdk.appId}`);
25
+ }
26
+ assertInitialized() {
27
+ if (!this.appId) {
28
+ console.error("AdTogether Error: SDK has not been initialized. Please call AdTogether.initialize() before displaying ads.");
29
+ return false;
30
+ }
31
+ return true;
32
+ }
33
+ static async fetchAd(adUnitId, adType) {
34
+ if (!_AdTogether.shared.assertInitialized()) {
35
+ throw new Error("AdTogether not initialized");
36
+ }
37
+ try {
38
+ const sdk = _AdTogether.shared;
39
+ let url = `${sdk.baseUrl}/api/ads/serve?country=global&adUnitId=${adUnitId}&apiKey=${sdk.appId}`;
40
+ if (adType) {
41
+ url += `&adType=${adType}`;
42
+ }
43
+ if (sdk.lastAdId) {
44
+ url += `&exclude=${sdk.lastAdId}`;
45
+ }
46
+ url += `&allowSelfAds=${sdk.allowSelfAds}`;
47
+ if (typeof window !== "undefined") {
48
+ url += `&sourceUrl=${encodeURIComponent(window.location.href)}`;
49
+ }
50
+ const response = await fetch(url);
51
+ if (response.ok) {
52
+ const ad = await response.json();
53
+ sdk.lastAdId = ad.id;
54
+ return ad;
55
+ }
56
+ throw new Error(`Failed to fetch ad. Status: ${response.status}`);
57
+ } catch (err) {
58
+ throw err;
59
+ }
60
+ }
61
+ static trackImpression(adId, token) {
62
+ this.trackEvent("/api/ads/impression", adId, token);
63
+ }
64
+ static trackClick(adId, token) {
65
+ this.trackEvent("/api/ads/click", adId, token);
66
+ }
67
+ static trackEvent(endpoint, adId, token) {
68
+ if (!_AdTogether.shared.assertInitialized()) return;
69
+ fetch(`${_AdTogether.shared.baseUrl}${endpoint}`, {
70
+ method: "POST",
71
+ headers: {
72
+ "Content-Type": "application/json"
73
+ },
74
+ body: JSON.stringify({
75
+ adId,
76
+ token,
77
+ apiKey: _AdTogether.shared.appId
78
+ })
79
+ }).catch(console.error);
80
+ }
81
+ };
82
+
83
+ export {
84
+ AdTogether
85
+ };
package/dist/index.d.mts CHANGED
@@ -1,27 +1,35 @@
1
+ type AdType = 'banner' | 'interstitial';
1
2
  interface AdModel {
2
3
  id: string;
3
4
  title: string;
4
5
  description: string;
5
6
  clickUrl?: string;
6
7
  imageUrl?: string;
8
+ token?: string;
9
+ adType?: AdType;
7
10
  }
8
11
  interface AdTogetherOptions {
9
- appId: string;
12
+ appId?: string;
13
+ apiKey?: string;
10
14
  baseUrl?: string;
15
+ /** Whether to show your own ads as fallback if no external ads are available. Defaults to true. */
16
+ allowSelfAds?: boolean;
11
17
  }
12
18
 
13
19
  declare class AdTogether {
14
20
  private static instance;
15
21
  private appId?;
22
+ private allowSelfAds;
16
23
  baseUrl: string;
17
24
  private constructor();
18
25
  static get shared(): AdTogether;
19
26
  static initialize(options: AdTogetherOptions): void;
20
27
  assertInitialized(): boolean;
21
- static fetchAd(adUnitId: string): Promise<AdModel>;
22
- static trackImpression(adId: string): void;
23
- static trackClick(adId: string): void;
28
+ private lastAdId?;
29
+ static fetchAd(adUnitId: string, adType?: AdType): Promise<AdModel>;
30
+ static trackImpression(adId: string, token?: string): void;
31
+ static trackClick(adId: string, token?: string): void;
24
32
  private static trackEvent;
25
33
  }
26
34
 
27
- export { type AdModel, AdTogether, type AdTogetherOptions };
35
+ export { type AdModel, AdTogether, type AdTogetherOptions, type AdType };
package/dist/index.d.ts CHANGED
@@ -1,27 +1,35 @@
1
+ type AdType = 'banner' | 'interstitial';
1
2
  interface AdModel {
2
3
  id: string;
3
4
  title: string;
4
5
  description: string;
5
6
  clickUrl?: string;
6
7
  imageUrl?: string;
8
+ token?: string;
9
+ adType?: AdType;
7
10
  }
8
11
  interface AdTogetherOptions {
9
- appId: string;
12
+ appId?: string;
13
+ apiKey?: string;
10
14
  baseUrl?: string;
15
+ /** Whether to show your own ads as fallback if no external ads are available. Defaults to true. */
16
+ allowSelfAds?: boolean;
11
17
  }
12
18
 
13
19
  declare class AdTogether {
14
20
  private static instance;
15
21
  private appId?;
22
+ private allowSelfAds;
16
23
  baseUrl: string;
17
24
  private constructor();
18
25
  static get shared(): AdTogether;
19
26
  static initialize(options: AdTogetherOptions): void;
20
27
  assertInitialized(): boolean;
21
- static fetchAd(adUnitId: string): Promise<AdModel>;
22
- static trackImpression(adId: string): void;
23
- static trackClick(adId: string): void;
28
+ private lastAdId?;
29
+ static fetchAd(adUnitId: string, adType?: AdType): Promise<AdModel>;
30
+ static trackImpression(adId: string, token?: string): void;
31
+ static trackClick(adId: string, token?: string): void;
24
32
  private static trackEvent;
25
33
  }
26
34
 
27
- export { type AdModel, AdTogether, type AdTogetherOptions };
35
+ export { type AdModel, AdTogether, type AdTogetherOptions, type AdType };
package/dist/index.js CHANGED
@@ -27,7 +27,8 @@ module.exports = __toCommonJS(index_exports);
27
27
  // src/core/AdTogether.ts
28
28
  var AdTogether = class _AdTogether {
29
29
  constructor() {
30
- this.baseUrl = "https://adtogether.com";
30
+ this.allowSelfAds = true;
31
+ this.baseUrl = "https://adtogether.relaxsoftwareapps.com";
31
32
  }
32
33
  static get shared() {
33
34
  if (!_AdTogether.instance) {
@@ -37,11 +38,16 @@ var AdTogether = class _AdTogether {
37
38
  }
38
39
  static initialize(options) {
39
40
  const sdk = _AdTogether.shared;
40
- sdk.appId = options.appId;
41
+ sdk.appId = options.apiKey || options.appId;
42
+ if (options.allowSelfAds !== void 0) {
43
+ sdk.allowSelfAds = options.allowSelfAds;
44
+ }
41
45
  if (options.baseUrl) {
42
46
  sdk.baseUrl = options.baseUrl;
47
+ } else if (typeof window !== "undefined") {
48
+ sdk.baseUrl = "";
43
49
  }
44
- console.log(`AdTogether SDK Initialized with App ID: ${options.appId}`);
50
+ console.log(`AdTogether SDK Initialized with App ID: ${sdk.appId}`);
45
51
  }
46
52
  assertInitialized() {
47
53
  if (!this.appId) {
@@ -50,30 +56,52 @@ var AdTogether = class _AdTogether {
50
56
  }
51
57
  return true;
52
58
  }
53
- static async fetchAd(adUnitId) {
59
+ static async fetchAd(adUnitId, adType) {
54
60
  if (!_AdTogether.shared.assertInitialized()) {
55
61
  throw new Error("AdTogether not initialized");
56
62
  }
57
- const response = await fetch(`${_AdTogether.shared.baseUrl}/api/ads/serve?country=global&adUnitId=${adUnitId}`);
58
- if (!response.ok) {
63
+ try {
64
+ const sdk = _AdTogether.shared;
65
+ let url = `${sdk.baseUrl}/api/ads/serve?country=global&adUnitId=${adUnitId}&apiKey=${sdk.appId}`;
66
+ if (adType) {
67
+ url += `&adType=${adType}`;
68
+ }
69
+ if (sdk.lastAdId) {
70
+ url += `&exclude=${sdk.lastAdId}`;
71
+ }
72
+ url += `&allowSelfAds=${sdk.allowSelfAds}`;
73
+ if (typeof window !== "undefined") {
74
+ url += `&sourceUrl=${encodeURIComponent(window.location.href)}`;
75
+ }
76
+ const response = await fetch(url);
77
+ if (response.ok) {
78
+ const ad = await response.json();
79
+ sdk.lastAdId = ad.id;
80
+ return ad;
81
+ }
59
82
  throw new Error(`Failed to fetch ad. Status: ${response.status}`);
83
+ } catch (err) {
84
+ throw err;
60
85
  }
61
- return response.json();
62
86
  }
63
- static trackImpression(adId) {
64
- this.trackEvent("/api/ads/impression", adId);
87
+ static trackImpression(adId, token) {
88
+ this.trackEvent("/api/ads/impression", adId, token);
65
89
  }
66
- static trackClick(adId) {
67
- this.trackEvent("/api/ads/click", adId);
90
+ static trackClick(adId, token) {
91
+ this.trackEvent("/api/ads/click", adId, token);
68
92
  }
69
- static trackEvent(endpoint, adId) {
93
+ static trackEvent(endpoint, adId, token) {
70
94
  if (!_AdTogether.shared.assertInitialized()) return;
71
95
  fetch(`${_AdTogether.shared.baseUrl}${endpoint}`, {
72
96
  method: "POST",
73
97
  headers: {
74
98
  "Content-Type": "application/json"
75
99
  },
76
- body: JSON.stringify({ adId })
100
+ body: JSON.stringify({
101
+ adId,
102
+ token,
103
+ apiKey: _AdTogether.shared.appId
104
+ })
77
105
  }).catch(console.error);
78
106
  }
79
107
  };
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  AdTogether
3
- } from "./chunk-IDJUJZAL.mjs";
3
+ } from "./chunk-7IJIBJD4.mjs";
4
4
  export {
5
5
  AdTogether
6
6
  };
@@ -15,4 +15,21 @@ interface AdTogetherBannerProps {
15
15
  }
16
16
  declare const AdTogetherBanner: React.FC<AdTogetherBannerProps>;
17
17
 
18
- export { AdTogetherBanner, type AdTogetherBannerProps };
18
+ interface AdTogetherInterstitialProps {
19
+ adUnitId: string;
20
+ /** When true, the interstitial is shown (fetches and displays full-screen ad) */
21
+ isOpen: boolean;
22
+ /** Called when the user closes the interstitial */
23
+ onClose: () => void;
24
+ /** Called when the ad is successfully loaded */
25
+ onAdLoaded?: () => void;
26
+ /** Called when the ad fails to load */
27
+ onAdFailedToLoad?: (error: Error) => void;
28
+ /** Pass 'dark' to use dark mode, 'light' for light mode, or 'auto' (default) to respect system preference */
29
+ theme?: 'dark' | 'light' | 'auto';
30
+ /** Delay in seconds before the close button appears. Defaults to 3 */
31
+ closeDelay?: number;
32
+ }
33
+ declare const AdTogetherInterstitial: React.FC<AdTogetherInterstitialProps>;
34
+
35
+ export { AdTogetherBanner, type AdTogetherBannerProps, AdTogetherInterstitial, type AdTogetherInterstitialProps };
@@ -15,4 +15,21 @@ interface AdTogetherBannerProps {
15
15
  }
16
16
  declare const AdTogetherBanner: React.FC<AdTogetherBannerProps>;
17
17
 
18
- export { AdTogetherBanner, type AdTogetherBannerProps };
18
+ interface AdTogetherInterstitialProps {
19
+ adUnitId: string;
20
+ /** When true, the interstitial is shown (fetches and displays full-screen ad) */
21
+ isOpen: boolean;
22
+ /** Called when the user closes the interstitial */
23
+ onClose: () => void;
24
+ /** Called when the ad is successfully loaded */
25
+ onAdLoaded?: () => void;
26
+ /** Called when the ad fails to load */
27
+ onAdFailedToLoad?: (error: Error) => void;
28
+ /** Pass 'dark' to use dark mode, 'light' for light mode, or 'auto' (default) to respect system preference */
29
+ theme?: 'dark' | 'light' | 'auto';
30
+ /** Delay in seconds before the close button appears. Defaults to 3 */
31
+ closeDelay?: number;
32
+ }
33
+ declare const AdTogetherInterstitial: React.FC<AdTogetherInterstitialProps>;
34
+
35
+ export { AdTogetherBanner, type AdTogetherBannerProps, AdTogetherInterstitial, type AdTogetherInterstitialProps };