@webaround/openai-ads 0.1.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/LICENSE +21 -0
- package/README.md +149 -0
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +15 -0
- package/dist/errors.js.map +1 -0
- package/dist/eventId.d.ts +26 -0
- package/dist/eventId.d.ts.map +1 -0
- package/dist/eventId.js +56 -0
- package/dist/eventId.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -0
- package/dist/pixel.d.ts +107 -0
- package/dist/pixel.d.ts.map +1 -0
- package/dist/pixel.js +305 -0
- package/dist/pixel.js.map +1 -0
- package/dist/spec.d.ts +26 -0
- package/dist/spec.d.ts.map +1 -0
- package/dist/spec.js +68 -0
- package/dist/spec.js.map +1 -0
- package/dist/types.d.ts +107 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/userData.d.ts +68 -0
- package/dist/userData.d.ts.map +1 -0
- package/dist/userData.js +172 -0
- package/dist/userData.js.map +1 -0
- package/package.json +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Webaround Labs
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
# @webaround/openai-ads
|
|
2
|
+
|
|
3
|
+
The OpenAI Ads Measurement Pixel for the browser: a typed, consent-aware wrapper
|
|
4
|
+
over the official `oaiq` SDK, built to deduplicate cleanly against the
|
|
5
|
+
Conversions API.
|
|
6
|
+
|
|
7
|
+
> **Pre-alpha, `0.1.x`.** Not published to npm. The public API is unstable until `1.0`.
|
|
8
|
+
|
|
9
|
+
## What this is, and is not
|
|
10
|
+
|
|
11
|
+
It **wraps** OpenAI's official browser SDK. It does not reimplement it. There is
|
|
12
|
+
no npm package to depend on — the official SDK is a script on OpenAI's CDN plus a
|
|
13
|
+
global command queue — so this package injects the documented loader and speaks
|
|
14
|
+
to that queue.
|
|
15
|
+
|
|
16
|
+
Everything the SDK owns stays with the SDK: batching, event timestamps,
|
|
17
|
+
`source_url`, and capturing `oppref` into the `__oppref` cookie. Passing any of
|
|
18
|
+
those by hand would corrupt them.
|
|
19
|
+
|
|
20
|
+
Zero runtime dependencies. ESM, tree-shakeable, `sideEffects: false`.
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { OpenAIAds } from '@webaround/openai-ads';
|
|
26
|
+
|
|
27
|
+
OpenAIAds.init({ pixelId: 'YOUR-PIXEL-ID' });
|
|
28
|
+
|
|
29
|
+
OpenAIAds.track('lead_created', undefined, { eventId: leadId });
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Amounts are integers in the currency's minor unit:
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
OpenAIAds.track('order_created', { amount: 2599, currency: 'EUR' }, { eventId: order.id });
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Pass `25.99` and you get a developer-friendly rejection — *"amount must be an
|
|
39
|
+
integer in the currency's minor unit; got 25.99. Did you mean 2599?"* — rather
|
|
40
|
+
than a silently wrong conversion value.
|
|
41
|
+
|
|
42
|
+
The data shape is supplied for you and is type-checked per event. `lead_created`
|
|
43
|
+
is a `customer_action`, which accepts no `contents` array, and TypeScript will say so.
|
|
44
|
+
|
|
45
|
+
### Identity
|
|
46
|
+
|
|
47
|
+
Hashing happens in the browser via Web Crypto, which is async and requires a
|
|
48
|
+
secure context. Raw values are never sent; if Web Crypto is unavailable, hashing
|
|
49
|
+
fails loudly instead of degrading.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { OpenAIAds, hashUser } from '@webaround/openai-ads';
|
|
53
|
+
|
|
54
|
+
OpenAIAds.init({ pixelId: 'YOUR-PIXEL-ID' });
|
|
55
|
+
|
|
56
|
+
// Later, once the visitor is known — after login, checkout or a lead submission:
|
|
57
|
+
OpenAIAds.init({ user: await hashUser({ email: user.email, country: 'RO' }) });
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Identity goes on `init`, not on each `track` call. `hashUser` produces the
|
|
61
|
+
Pixel's singular-key shape (`email_sha256`), which differs from the Conversions
|
|
62
|
+
API's plural arrays (`emails_sha256`) — the digests are identical, the shapes are
|
|
63
|
+
not.
|
|
64
|
+
|
|
65
|
+
### Consent
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
OpenAIAds.consent(false); // before init
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Denied consent means the SDK is never loaded and `track()` becomes a **silent
|
|
72
|
+
no-op** — a refused consent is a normal outcome, not an error.
|
|
73
|
+
|
|
74
|
+
`optOut` is a different thing. It excludes an event from personalization while
|
|
75
|
+
still sending it. Do not wire a consent banner to `optOut`: that still transmits
|
|
76
|
+
identity hashes.
|
|
77
|
+
|
|
78
|
+
### Deduplication
|
|
79
|
+
|
|
80
|
+
The key is Pixel ID + event name + event id. The browser event and its
|
|
81
|
+
server-side twin must share all three.
|
|
82
|
+
|
|
83
|
+
Prefer an id the server already owns, and prefer to learn it *from* the server:
|
|
84
|
+
|
|
85
|
+
1. the server completes the business action and knows the record's id;
|
|
86
|
+
2. it returns that id (AJAX) or renders it into the confirmation page;
|
|
87
|
+
3. it sends the Conversions API event with that id;
|
|
88
|
+
4. the browser fires the Pixel event with the same id.
|
|
89
|
+
|
|
90
|
+
`createEventId()` is the fallback for flows where no such id exists when the
|
|
91
|
+
browser must act — mint it once, send it with the request, and never regenerate
|
|
92
|
+
it. A retry that re-mints is a second conversion. It uses Web Crypto and throws
|
|
93
|
+
rather than falling back to `Math.random()`, because a collision silently merges
|
|
94
|
+
two people's conversions.
|
|
95
|
+
|
|
96
|
+
### Multiple pixels
|
|
97
|
+
|
|
98
|
+
`measure` broadcasts to **every** pixel initialized at the time of the call —
|
|
99
|
+
that is the SDK's documented behaviour, preserved here. On a multi-pixel page
|
|
100
|
+
that usually double-counts, so target one explicitly:
|
|
101
|
+
|
|
102
|
+
```ts
|
|
103
|
+
OpenAIAds.init({ pixelId: 'px-a' });
|
|
104
|
+
OpenAIAds.init({ pixelId: 'px-b' });
|
|
105
|
+
|
|
106
|
+
OpenAIAds.track('order_created', data, { pixelId: 'px-b', eventId: order.id });
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Errors never reach your code
|
|
110
|
+
|
|
111
|
+
`track()` and `init()` do not throw. A measurement mistake on a checkout page
|
|
112
|
+
must not take the checkout with it, so failures are routed to a handler:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
OpenAIAds.configure({ onError: (error) => Sentry.captureException(error) });
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
This is the opposite of the PHP core, which throws — there, the caller is server
|
|
119
|
+
code that decides what to do, and swallowing a developer error would hide it.
|
|
120
|
+
|
|
121
|
+
## Never put the CAPI key here
|
|
122
|
+
|
|
123
|
+
The Conversions API key is server-side only. Nothing in this package accepts one.
|
|
124
|
+
It must never appear in JavaScript, a public environment variable, HTML, or a
|
|
125
|
+
browser bundle.
|
|
126
|
+
|
|
127
|
+
## Development
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
npm install
|
|
131
|
+
npm test
|
|
132
|
+
npm run typecheck
|
|
133
|
+
npm run build
|
|
134
|
+
npx vitest run tests/userData.test.ts # a single file
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
`tests/spec-parity.test.ts` asserts this package against `packages/spec` — the
|
|
138
|
+
event catalogue, the data shapes, Pixel support, and the Pixel identity key set.
|
|
139
|
+
The normalization tests read
|
|
140
|
+
`packages/spec/fixtures/normalization.cases.json` directly, which is the same
|
|
141
|
+
file the PHP suite asserts against: that is what guarantees a browser event and a
|
|
142
|
+
server event describe the same person.
|
|
143
|
+
|
|
144
|
+
Those tests read the spec by relative path, so they run from a monorepo checkout
|
|
145
|
+
only.
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
|
|
149
|
+
[MIT](../../LICENSE). Independent community project, not affiliated with OpenAI.
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every error this package produces.
|
|
3
|
+
*
|
|
4
|
+
* Unlike the PHP core, these are almost never thrown at the caller: on a web
|
|
5
|
+
* page a measurement mistake must not break a checkout, so `track()` routes
|
|
6
|
+
* failures to `onError` instead. The class exists so a host application can
|
|
7
|
+
* recognize them when it supplies its own handler.
|
|
8
|
+
*/
|
|
9
|
+
export declare class OpenAIAdsError extends Error {
|
|
10
|
+
readonly name = "OpenAIAdsError";
|
|
11
|
+
constructor(message: string, options?: {
|
|
12
|
+
cause?: unknown;
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,qBAAa,cAAe,SAAQ,KAAK;IACvC,SAAkB,IAAI,oBAAoB;gBAE9B,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE;CAG3D"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every error this package produces.
|
|
3
|
+
*
|
|
4
|
+
* Unlike the PHP core, these are almost never thrown at the caller: on a web
|
|
5
|
+
* page a measurement mistake must not break a checkout, so `track()` routes
|
|
6
|
+
* failures to `onError` instead. The class exists so a host application can
|
|
7
|
+
* recognize them when it supplies its own handler.
|
|
8
|
+
*/
|
|
9
|
+
export class OpenAIAdsError extends Error {
|
|
10
|
+
constructor(message, options) {
|
|
11
|
+
super(message, options);
|
|
12
|
+
this.name = 'OpenAIAdsError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,OAAO,cAAe,SAAQ,KAAK;IAGvC,YAAY,OAAe,EAAE,OAA6B;QACxD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAHR,SAAI,GAAG,gBAAgB,CAAC;IAI1C,CAAC;CACF"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deduplication identifiers.
|
|
3
|
+
*
|
|
4
|
+
* The key is Pixel ID + event name + event id, so the browser event and its
|
|
5
|
+
* server-side twin must carry the same value.
|
|
6
|
+
*
|
|
7
|
+
* Prefer an id the server already owns - an order id, a payment intent id, a
|
|
8
|
+
* lead id - and prefer to learn it FROM the server rather than minting one here:
|
|
9
|
+
*
|
|
10
|
+
* 1. the server completes the business action and knows the record's id;
|
|
11
|
+
* 2. it returns that id (AJAX) or renders it into the confirmation page;
|
|
12
|
+
* 3. it sends the Conversions API event with that id;
|
|
13
|
+
* 4. the browser fires the Pixel event with the same id.
|
|
14
|
+
*
|
|
15
|
+
* `createEventId()` is the fallback for flows where no such id exists at the
|
|
16
|
+
* moment the browser must act. Mint it once, send it to the server with the
|
|
17
|
+
* request, and never regenerate it - a retry that re-mints is a second
|
|
18
|
+
* conversion.
|
|
19
|
+
*/
|
|
20
|
+
export declare function createEventId(): string;
|
|
21
|
+
/**
|
|
22
|
+
* Rejects an unusable id rather than letting an empty string become a
|
|
23
|
+
* deduplication key that matches everything.
|
|
24
|
+
*/
|
|
25
|
+
export declare function assertUsableEventId(id: string): string;
|
|
26
|
+
//# sourceMappingURL=eventId.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventId.d.ts","sourceRoot":"","sources":["../src/eventId.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,aAAa,IAAI,MAAM,CA6BtC;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAQtD"}
|
package/dist/eventId.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { OpenAIAdsError } from './errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Deduplication identifiers.
|
|
4
|
+
*
|
|
5
|
+
* The key is Pixel ID + event name + event id, so the browser event and its
|
|
6
|
+
* server-side twin must carry the same value.
|
|
7
|
+
*
|
|
8
|
+
* Prefer an id the server already owns - an order id, a payment intent id, a
|
|
9
|
+
* lead id - and prefer to learn it FROM the server rather than minting one here:
|
|
10
|
+
*
|
|
11
|
+
* 1. the server completes the business action and knows the record's id;
|
|
12
|
+
* 2. it returns that id (AJAX) or renders it into the confirmation page;
|
|
13
|
+
* 3. it sends the Conversions API event with that id;
|
|
14
|
+
* 4. the browser fires the Pixel event with the same id.
|
|
15
|
+
*
|
|
16
|
+
* `createEventId()` is the fallback for flows where no such id exists at the
|
|
17
|
+
* moment the browser must act. Mint it once, send it to the server with the
|
|
18
|
+
* request, and never regenerate it - a retry that re-mints is a second
|
|
19
|
+
* conversion.
|
|
20
|
+
*/
|
|
21
|
+
export function createEventId() {
|
|
22
|
+
const cryptoRef = globalThis.crypto;
|
|
23
|
+
if (typeof cryptoRef?.randomUUID === 'function') {
|
|
24
|
+
return cryptoRef.randomUUID();
|
|
25
|
+
}
|
|
26
|
+
if (typeof cryptoRef?.getRandomValues === 'function') {
|
|
27
|
+
const bytes = cryptoRef.getRandomValues(new Uint8Array(16));
|
|
28
|
+
// RFC 4122 version 4.
|
|
29
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
|
|
30
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
|
|
31
|
+
const hex = [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('');
|
|
32
|
+
return [
|
|
33
|
+
hex.slice(0, 8),
|
|
34
|
+
hex.slice(8, 12),
|
|
35
|
+
hex.slice(12, 16),
|
|
36
|
+
hex.slice(16, 20),
|
|
37
|
+
hex.slice(20),
|
|
38
|
+
].join('-');
|
|
39
|
+
}
|
|
40
|
+
// Math.random() is deliberately NOT used as a further fallback. A weak id can
|
|
41
|
+
// collide, and a collision silently merges two people's conversions.
|
|
42
|
+
throw new OpenAIAdsError('Cannot generate an event id: this browser exposes no Web Crypto. ' +
|
|
43
|
+
'Supply a stable business id from the server instead.');
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Rejects an unusable id rather than letting an empty string become a
|
|
47
|
+
* deduplication key that matches everything.
|
|
48
|
+
*/
|
|
49
|
+
export function assertUsableEventId(id) {
|
|
50
|
+
const trimmed = id.trim();
|
|
51
|
+
if (trimmed === '') {
|
|
52
|
+
throw new OpenAIAdsError('eventId must be a non-empty string.');
|
|
53
|
+
}
|
|
54
|
+
return trimmed;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=eventId.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"eventId.js","sourceRoot":"","sources":["../src/eventId.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,aAAa;IAC3B,MAAM,SAAS,GAAG,UAAU,CAAC,MAAM,CAAC;IAEpC,IAAI,OAAO,SAAS,EAAE,UAAU,KAAK,UAAU,EAAE,CAAC;QAChD,OAAO,SAAS,CAAC,UAAU,EAAE,CAAC;IAChC,CAAC;IAED,IAAI,OAAO,SAAS,EAAE,eAAe,KAAK,UAAU,EAAE,CAAC;QACrD,MAAM,KAAK,GAAG,SAAS,CAAC,eAAe,CAAC,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5D,sBAAsB;QACtB,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QACrC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QACrC,MAAM,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAE5E,OAAO;YACL,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;YACf,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;YAChB,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;YACjB,GAAG,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,CAAC;YACjB,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;SACd,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACd,CAAC;IAED,8EAA8E;IAC9E,qEAAqE;IACrE,MAAM,IAAI,cAAc,CACtB,mEAAmE;QACjE,sDAAsD,CACzD,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAAU;IAC5C,MAAM,OAAO,GAAG,EAAE,CAAC,IAAI,EAAE,CAAC;IAE1B,IAAI,OAAO,KAAK,EAAE,EAAE,CAAC;QACnB,MAAM,IAAI,cAAc,CAAC,qCAAqC,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { OpenAIAds, OpenAIAdsPixel } from './pixel.js';
|
|
2
|
+
export { OpenAIAdsError } from './errors.js';
|
|
3
|
+
export { createEventId } from './eventId.js';
|
|
4
|
+
export { hashUser, sha256Hex, normalizeEmail, normalizeName, normalizePhone, normalizeExternalId, normalizeCountry, normalizeCityOrRegion, normalizePostalCode, } from './userData.js';
|
|
5
|
+
export { EVENT_NAMES, DATA_SHAPES, PIXEL_SUPPORTED, CUSTOM_EVENT_NAME_PATTERN, SDK_URL, isEventName, } from './spec.js';
|
|
6
|
+
export type { EventName, DataShape } from './spec.js';
|
|
7
|
+
export type { Content, ContentsData, CustomData, CustomerActionData, EventData, InitConfig, PixelUser, PlanEnrollmentData, RawUser, ToolkitOptions, TrackOptions, } from './types.js';
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,QAAQ,EACR,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,WAAW,EACX,WAAW,EACX,eAAe,EACf,yBAAyB,EACzB,OAAO,EACP,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtD,YAAY,EACV,OAAO,EACP,YAAY,EACZ,UAAU,EACV,kBAAkB,EAClB,SAAS,EACT,UAAU,EACV,SAAS,EACT,kBAAkB,EAClB,OAAO,EACP,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export { OpenAIAds, OpenAIAdsPixel } from './pixel.js';
|
|
2
|
+
export { OpenAIAdsError } from './errors.js';
|
|
3
|
+
export { createEventId } from './eventId.js';
|
|
4
|
+
export { hashUser, sha256Hex, normalizeEmail, normalizeName, normalizePhone, normalizeExternalId, normalizeCountry, normalizeCityOrRegion, normalizePostalCode, } from './userData.js';
|
|
5
|
+
export { EVENT_NAMES, DATA_SHAPES, PIXEL_SUPPORTED, CUSTOM_EVENT_NAME_PATTERN, SDK_URL, isEventName, } from './spec.js';
|
|
6
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,EACL,QAAQ,EACR,SAAS,EACT,cAAc,EACd,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,WAAW,EACX,WAAW,EACX,eAAe,EACf,yBAAyB,EACzB,OAAO,EACP,WAAW,GACZ,MAAM,WAAW,CAAC"}
|
package/dist/pixel.d.ts
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import type { EventName } from './spec.js';
|
|
2
|
+
import type { DataFor, EventData, InitConfig, ToolkitOptions, TrackOptions } from './types.js';
|
|
3
|
+
type OaiqQueue = ((...args: unknown[]) => void) & {
|
|
4
|
+
q?: unknown[];
|
|
5
|
+
};
|
|
6
|
+
declare global {
|
|
7
|
+
var oaiq: OaiqQueue | undefined;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A typed, consent-aware wrapper over OpenAI's official browser SDK.
|
|
11
|
+
*
|
|
12
|
+
* It does NOT reimplement the transport. The official SDK is a script on
|
|
13
|
+
* OpenAI's CDN plus a global command queue, and this wrapper loads that script
|
|
14
|
+
* and speaks to that queue. Everything the SDK owns - batching, timestamps,
|
|
15
|
+
* `source_url`, capturing `oppref` into the `__oppref` cookie - is left to it.
|
|
16
|
+
*
|
|
17
|
+
* Nothing here throws at the caller. A measurement failure must never break a
|
|
18
|
+
* checkout or a form submission, so errors go to `onError`.
|
|
19
|
+
*/
|
|
20
|
+
declare class OpenAIAdsPixel {
|
|
21
|
+
private readonly pixelIds;
|
|
22
|
+
private debug;
|
|
23
|
+
private consentGranted;
|
|
24
|
+
private scriptInjected;
|
|
25
|
+
private onError;
|
|
26
|
+
/**
|
|
27
|
+
* Configure error reporting. Optional; call before `init` to catch setup
|
|
28
|
+
* problems.
|
|
29
|
+
*/
|
|
30
|
+
configure(options: ToolkitOptions): void;
|
|
31
|
+
/**
|
|
32
|
+
* Record the visitor's consent decision.
|
|
33
|
+
*
|
|
34
|
+
* Must be called before `init` to take effect on the SDK, per its
|
|
35
|
+
* documentation. When consent is denied this wrapper also stops emitting
|
|
36
|
+
* events of its own accord - silently, because a refused consent is a normal
|
|
37
|
+
* outcome and not an error.
|
|
38
|
+
*/
|
|
39
|
+
consent(granted: boolean): void;
|
|
40
|
+
/**
|
|
41
|
+
* Load the SDK and initialize a Pixel ID.
|
|
42
|
+
*
|
|
43
|
+
* Safe to call more than once, which is required rather than merely tolerated:
|
|
44
|
+
* the documented way to attach identity once a visitor becomes known is to
|
|
45
|
+
* call init again with `user`. Re-initializing the same Pixel ID with no new
|
|
46
|
+
* user data is skipped, which is the guard against the common mistake of
|
|
47
|
+
* initializing in both a root layout and a page.
|
|
48
|
+
*
|
|
49
|
+
* On a page with several pixels, call this once per Pixel ID.
|
|
50
|
+
*/
|
|
51
|
+
init(config?: InitConfig): void;
|
|
52
|
+
/**
|
|
53
|
+
* Emit a standard event at a confirmed conversion boundary.
|
|
54
|
+
*
|
|
55
|
+
* Fire after the action has succeeded - after payment is confirmed, after the
|
|
56
|
+
* lead is accepted - never on a button click, unless the click genuinely is
|
|
57
|
+
* the conversion.
|
|
58
|
+
*/
|
|
59
|
+
track<N extends EventName>(name: N, data?: Partial<DataFor<N>>, options?: TrackOptions): void;
|
|
60
|
+
/**
|
|
61
|
+
* Emit a custom event.
|
|
62
|
+
*
|
|
63
|
+
* Use only where no standard event describes the action. The same name must be
|
|
64
|
+
* used on the Conversions API side or the two will not deduplicate.
|
|
65
|
+
*/
|
|
66
|
+
trackCustom(customEventName: string, data?: Partial<Omit<EventData, 'type'>>, options?: Omit<TrackOptions, 'customEventName'>): void;
|
|
67
|
+
/** Pixel IDs initialized so far. Exposed for diagnostics and tests. */
|
|
68
|
+
initializedPixelIds(): string[];
|
|
69
|
+
/** Test seam. Not part of the public API. */
|
|
70
|
+
reset(): void;
|
|
71
|
+
/**
|
|
72
|
+
* `name` is a string rather than an EventName on purpose.
|
|
73
|
+
*
|
|
74
|
+
* TypeScript proves the caller passed a valid one; JavaScript proves nothing,
|
|
75
|
+
* and this package is published for both. The check below is what a plain-JS
|
|
76
|
+
* caller gets instead of a compile error.
|
|
77
|
+
*/
|
|
78
|
+
private emit;
|
|
79
|
+
private buildData;
|
|
80
|
+
private buildOptions;
|
|
81
|
+
private validateCustomEventName;
|
|
82
|
+
/**
|
|
83
|
+
* Create the global command queue.
|
|
84
|
+
*
|
|
85
|
+
* This is the first half of the documented loader snippet: define the queue
|
|
86
|
+
* synchronously so commands issued before the script arrives are replayed in
|
|
87
|
+
* order. Kept separate from injecting the script so that `consent(false)` can
|
|
88
|
+
* be recorded on a page where the SDK is never loaded at all.
|
|
89
|
+
*/
|
|
90
|
+
private ensureQueue;
|
|
91
|
+
/** The second half of the loader snippet: fetch the official SDK, once. */
|
|
92
|
+
private load;
|
|
93
|
+
private queue;
|
|
94
|
+
/**
|
|
95
|
+
* The reason nothing here throws at the caller.
|
|
96
|
+
*
|
|
97
|
+
* A measurement mistake on a checkout page must not take the checkout with it,
|
|
98
|
+
* so failures are reported and swallowed. Supply `onError` to route them into
|
|
99
|
+
* your own logging.
|
|
100
|
+
*/
|
|
101
|
+
private safely;
|
|
102
|
+
private warn;
|
|
103
|
+
}
|
|
104
|
+
export { OpenAIAdsPixel };
|
|
105
|
+
/** The shared instance. A page has one Pixel SDK, so it has one of these. */
|
|
106
|
+
export declare const OpenAIAds: OpenAIAdsPixel;
|
|
107
|
+
//# sourceMappingURL=pixel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pixel.d.ts","sourceRoot":"","sources":["../src/pixel.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE/F,KAAK,SAAS,GAAG,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,CAAC,GAAG;IAAE,CAAC,CAAC,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC;AAEpE,OAAO,CAAC,MAAM,CAAC;IACb,IAAI,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;CACjC;AAED;;;;;;;;;;GAUG;AACH,cAAM,cAAc;IAClB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqB;IAE9C,OAAO,CAAC,KAAK,CAAS;IAEtB,OAAO,CAAC,cAAc,CAAQ;IAE9B,OAAO,CAAC,cAAc,CAAS;IAE/B,OAAO,CAAC,OAAO,CAAoC;IAEnD;;;OAGG;IACH,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAMxC;;;;;;;OAOG;IACH,OAAO,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;IAa/B;;;;;;;;;;OAUG;IACH,IAAI,CAAC,MAAM,GAAE,UAAe,GAAG,IAAI;IAmDnC;;;;;;OAMG;IACH,KAAK,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,GAAE,YAAiB,GAAG,IAAI;IAMjG;;;;;OAKG;IACH,WAAW,CACT,eAAe,EAAE,MAAM,EACvB,IAAI,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,EACvC,OAAO,GAAE,IAAI,CAAC,YAAY,EAAE,iBAAiB,CAAM,GAClD,IAAI;IAMP,uEAAuE;IACvE,mBAAmB,IAAI,MAAM,EAAE;IAI/B,6CAA6C;IAC7C,KAAK,IAAI,IAAI;IAQb;;;;;;OAMG;IACH,OAAO,CAAC,IAAI;IAiDZ,OAAO,CAAC,SAAS;IAgCjB,OAAO,CAAC,YAAY;IAqBpB,OAAO,CAAC,uBAAuB;IA+B/B;;;;;;;OAOG;IACH,OAAO,CAAC,WAAW;IAYnB,2EAA2E;IAC3E,OAAO,CAAC,IAAI;IA+BZ,OAAO,CAAC,KAAK;IAUb;;;;;;OAMG;IACH,OAAO,CAAC,MAAM;IAed,OAAO,CAAC,IAAI;CAKb;AAED,OAAO,EAAE,cAAc,EAAE,CAAC;AAE1B,6EAA6E;AAC7E,eAAO,MAAM,SAAS,gBAAuB,CAAC"}
|