@astroscope/relay 0.0.0-stage → 1.0.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 +236 -2
- package/dist/awin/index.d.ts +57 -0
- package/dist/awin/index.d.ts.map +1 -0
- package/dist/awin/index.js +54 -0
- package/dist/awin/index.js.map +1 -0
- package/dist/bus-Z7l8oJtS.d.ts +48 -0
- package/dist/bus-Z7l8oJtS.d.ts.map +1 -0
- package/dist/ccm19/index.d.ts +33 -0
- package/dist/ccm19/index.d.ts.map +1 -0
- package/dist/ccm19/index.js +29 -0
- package/dist/ccm19/index.js.map +1 -0
- package/dist/client/index.d.ts +16 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +24 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/track.d.ts +4 -0
- package/dist/client/track.d.ts.map +1 -0
- package/dist/client/track.js +7 -0
- package/dist/client/track.js.map +1 -0
- package/dist/collect-DRl177oR.d.ts +31 -0
- package/dist/collect-DRl177oR.d.ts.map +1 -0
- package/dist/collect-DWdHyn-u.js +45 -0
- package/dist/collect-DWdHyn-u.js.map +1 -0
- package/dist/commerce-DCGO8yag.d.ts +106 -0
- package/dist/commerce-DCGO8yag.d.ts.map +1 -0
- package/dist/commerce-DgNeBWhO.js +46 -0
- package/dist/commerce-DgNeBWhO.js.map +1 -0
- package/dist/context-D11BBDcb.js +27 -0
- package/dist/context-D11BBDcb.js.map +1 -0
- package/dist/conversion-user-CV8xIWDK.js +49 -0
- package/dist/conversion-user-CV8xIWDK.js.map +1 -0
- package/dist/conversion-user-DCfM5EuZ.d.ts +35 -0
- package/dist/conversion-user-DCfM5EuZ.d.ts.map +1 -0
- package/dist/ga4/index.d.ts +50 -0
- package/dist/ga4/index.d.ts.map +1 -0
- package/dist/ga4/index.js +45 -0
- package/dist/ga4/index.js.map +1 -0
- package/dist/gtm/index.d.ts +51 -0
- package/dist/gtm/index.d.ts.map +1 -0
- package/dist/gtm/index.js +49 -0
- package/dist/gtm/index.js.map +1 -0
- package/dist/index.browser.d.ts +8 -0
- package/dist/index.browser.d.ts.map +1 -0
- package/dist/index.browser.js +11 -0
- package/dist/index.browser.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +73 -0
- package/dist/index.js.map +1 -0
- package/dist/instance-Bu0EMJ_-.js +268 -0
- package/dist/instance-Bu0EMJ_-.js.map +1 -0
- package/dist/matomo/index.d.ts +46 -0
- package/dist/matomo/index.d.ts.map +1 -0
- package/dist/matomo/index.js +61 -0
- package/dist/matomo/index.js.map +1 -0
- package/dist/openai/index.d.ts +97 -0
- package/dist/openai/index.d.ts.map +1 -0
- package/dist/openai/index.js +79 -0
- package/dist/openai/index.js.map +1 -0
- package/dist/openai/server.d.ts +17 -0
- package/dist/openai/server.d.ts.map +1 -0
- package/dist/openai/server.js +55 -0
- package/dist/openai/server.js.map +1 -0
- package/dist/react/index.d.ts +7 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +13 -0
- package/dist/react/index.js.map +1 -0
- package/dist/runtime-J8VplGyY.d.ts +48 -0
- package/dist/runtime-J8VplGyY.d.ts.map +1 -0
- package/dist/server/index.d.ts +18 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +10 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/middleware-entrypoint.d.ts +2 -0
- package/dist/server/middleware-entrypoint.d.ts.map +1 -0
- package/dist/server/middleware-entrypoint.js +25 -0
- package/dist/server/middleware-entrypoint.js.map +1 -0
- package/dist/server/registry.d.ts +9 -0
- package/dist/server/registry.d.ts.map +1 -0
- package/dist/server/registry.js +10 -0
- package/dist/server/registry.js.map +1 -0
- package/dist/server/track.d.ts +10 -0
- package/dist/server/track.d.ts.map +1 -0
- package/dist/server/track.js +90 -0
- package/dist/server/track.js.map +1 -0
- package/dist/shared-CSwqcxPI.d.ts +77 -0
- package/dist/shared-CSwqcxPI.d.ts.map +1 -0
- package/dist/shared-D281USsp.js +106 -0
- package/dist/shared-D281USsp.js.map +1 -0
- package/package.json +133 -3
- package/src/astro/Track.astro +16 -0
- package/src/astro/index.ts +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025-2026 entwico GmbH
|
|
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
CHANGED
|
@@ -1,3 +1,237 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @astroscope/relay
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **Disclaimer.** A technical tool, not legal advice: it forwards events only where your consent source says the visitor agreed, but compliance with GDPR, ePrivacy or any other law stays your responsibility. No guarantee, no liability.
|
|
4
|
+
|
|
5
|
+
Consent-aware event relay for Astro. The site defines each event once, as the payloads of the destinations it is meant for. One `track()` puts the event on a bus in the browser and reports it from an action on the server. A destination takes its payload once the visitor consented to it. The package never binds to a consent management platform: the site answers the consent question through one function, and the server reads the browser's answers off a header the bus attaches to every request.
|
|
6
|
+
|
|
7
|
+
What it solves:
|
|
8
|
+
|
|
9
|
+
- **One definition per event.** `purchase` is the data layer push, the conversions api order and the affiliate sale in one place.
|
|
10
|
+
- **Late destinations.** A cmp injects a pixel some time after consent. Events tracked before that wait on the bus until the destination is ready.
|
|
11
|
+
- **Late consent.** Events tracked before the visitor chose stay in memory and flow once they accept.
|
|
12
|
+
- **Double counting.** The browser pixel and the server-side conversions api fire under one event id.
|
|
13
|
+
- **Forgotten gates.** An action never checks consent itself. The bus writes the `x-relay-consent` header onto every same-origin `fetch` and nowhere else, the middleware reads it, and the server `track()` reports to consented destinations only. Events live in memory; nothing is stored on the device.
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pnpm add @astroscope/relay
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Requires `@astroscope/node` as the adapter. React is optional, for `@astroscope/relay/react`.
|
|
22
|
+
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
// astro.config.ts
|
|
27
|
+
import node from '@astroscope/node';
|
|
28
|
+
import relay from '@astroscope/relay';
|
|
29
|
+
import { defineConfig } from 'astro/config';
|
|
30
|
+
|
|
31
|
+
export default defineConfig({
|
|
32
|
+
adapter: node(),
|
|
33
|
+
integrations: [relay()],
|
|
34
|
+
});
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
The integration takes no options. It owns `src/relay/`, where a file's existence switches a half on:
|
|
38
|
+
|
|
39
|
+
| File | Role |
|
|
40
|
+
| --------------------- | ------------------------------------------------------------------------------------ |
|
|
41
|
+
| `src/relay/client.ts` | The browser bus configuration, as its default export; loaded on every page |
|
|
42
|
+
| `src/relay/server.ts` | The registry of server destinations; what the server `track()` reports to |
|
|
43
|
+
| `src/relay/events.ts` | The events; a plain module the integration never touches |
|
|
44
|
+
|
|
45
|
+
The middleware that reads the consent header is always added, so `relayConsent()` works regardless.
|
|
46
|
+
|
|
47
|
+
## Events
|
|
48
|
+
|
|
49
|
+
A definition takes the site's own objects and returns one payload per destination, under the destination's name, built with that destination's builders. The export is the key plus `Event`, one export per event, so an island bundles only the events it tracks and an event only an action imports never reaches the browser.
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
// src/relay/events.ts
|
|
53
|
+
import { type ConversionUser, defineEvent } from '@astroscope/relay';
|
|
54
|
+
import { ga4 } from '@astroscope/relay/ga4';
|
|
55
|
+
import { openai } from '@astroscope/relay/openai';
|
|
56
|
+
|
|
57
|
+
const toItem = (product: ProductCard) => ({ item_id: product.id, item_name: product.name, price: product.price, quantity: 1 });
|
|
58
|
+
|
|
59
|
+
export const viewProductEvent = defineEvent('viewProduct', (product: ProductCard) => ({
|
|
60
|
+
ga4: ga4.viewItem({ items: [toItem(product)] }),
|
|
61
|
+
openai: openai.contentsViewed({ items: [{ id: product.id, name: product.name, price: product.price, quantity: 1 }], currency: 'EUR' }),
|
|
62
|
+
}));
|
|
63
|
+
|
|
64
|
+
export const selectOfferEvent = defineEvent('selectOffer', (offer: OfferCard) => ({
|
|
65
|
+
ga4: ga4.selectItem({ item_list_name: 'offers', items: [{ ...toItem(offer.product), affiliation: offer.seller }] }),
|
|
66
|
+
}));
|
|
67
|
+
|
|
68
|
+
export const searchEvent = defineEvent('search', (term: string) => ({ ga4: ga4.search({ search_term: term }) }));
|
|
69
|
+
|
|
70
|
+
export const newsletterEvent = defineEvent('newsletter', (lead: { id?: string; user: ConversionUser }) => ({
|
|
71
|
+
id: lead.id,
|
|
72
|
+
ga4: ga4.signUp({ method: 'newsletter' }),
|
|
73
|
+
openai: openai.leadCreated(lead.user),
|
|
74
|
+
}));
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
The optional `id` is the event's own id, an order number for example. Every destination on both sides then counts the conversion once. Without it, each `track()` call gets a fresh id.
|
|
78
|
+
|
|
79
|
+
The ga4 and gtm builders cover GA4's recommended events, typed by their parameters. `ga4.event(name, params)` and `gtm.event(name, params)` take any other name. A tag-manager container keeps its own event names: `gtm.event('contactFormStatus', { status: 'success' })`.
|
|
80
|
+
|
|
81
|
+
Payload types are checked by name through the `RelayDestinations` interface. Each destination entry adds its own; a site's own destination does the same:
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
export type CrmEvent = { kind: string; email: string };
|
|
85
|
+
|
|
86
|
+
declare module '@astroscope/relay' {
|
|
87
|
+
interface RelayDestinations {
|
|
88
|
+
crm: CrmEvent;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Tracking in the browser
|
|
94
|
+
|
|
95
|
+
An island calls `track()`. A page tracks from server-rendered html with `<Track>`. A link or button tracks on click through the `data-track` attribute, which the bus listens for itself, before hydration too.
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
import { track } from '@astroscope/relay/track';
|
|
99
|
+
|
|
100
|
+
track(searchEvent(term));
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
```astro
|
|
104
|
+
---
|
|
105
|
+
import { trackAttribute } from '@astroscope/relay';
|
|
106
|
+
import { Track } from '@astroscope/relay/astro';
|
|
107
|
+
---
|
|
108
|
+
<Track event={viewProductEvent(product)} />
|
|
109
|
+
<a href={offer.url} rel="sponsored" data-track={trackAttribute(selectOfferEvent(offer))}>Zum Angebot</a>
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
```tsx
|
|
113
|
+
import { Track } from '@astroscope/relay/react';
|
|
114
|
+
|
|
115
|
+
<Track event={viewProductListEvent(products)} />
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`@astroscope/relay/track` is the same import in an island and in an action: in the browser it is the bus, on the server the conversions reporter. `inlineTrack(event)` from the root entry gives the script body for hand-written html.
|
|
119
|
+
|
|
120
|
+
### Batching list sightings
|
|
121
|
+
|
|
122
|
+
A list is seen one item at a time as rows enter the viewport, while `view_item_list` is one event with all items. `collect()` folds the sightings into batches: one buffer per key, flushed after a quiet time, at most `max` items per batch. A string context is its own key; an object context needs a `key` function.
|
|
123
|
+
|
|
124
|
+
```ts
|
|
125
|
+
export const viewProductListItem = collect({
|
|
126
|
+
flush: (list: string, items: ListedItem[]) => track(viewProductListEvent(list, items)),
|
|
127
|
+
within: 500,
|
|
128
|
+
max: 16,
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
viewProductListItem(listName, item);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
## The browser bus
|
|
135
|
+
|
|
136
|
+
`src/relay/client.ts` default-exports `defineRelayClient({ destinations, consent, debug? })`. A promise is awaited. The destinations are registered under their names, the same keys the events put their payloads under. The consent source must cover exactly those names, which the types enforce.
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
// src/relay/client.ts
|
|
140
|
+
import { ccm19 } from '@astroscope/relay/ccm19';
|
|
141
|
+
import { defineRelayClient } from '@astroscope/relay/client';
|
|
142
|
+
import { ga4Tag } from '@astroscope/relay/ga4';
|
|
143
|
+
import { gtmContainer } from '@astroscope/relay/gtm';
|
|
144
|
+
import { matomoTracker } from '@astroscope/relay/matomo';
|
|
145
|
+
|
|
146
|
+
export default defineRelayClient({
|
|
147
|
+
destinations: { gtm: gtmContainer(), ga4: ga4Tag(), matomo: matomoTracker() },
|
|
148
|
+
consent: ccm19({
|
|
149
|
+
gtm: { embedding: Config.gtm.ccmEmbeddingId },
|
|
150
|
+
ga4: { cookie: (pattern) => pattern.startsWith('_ga') },
|
|
151
|
+
matomo: false,
|
|
152
|
+
}),
|
|
153
|
+
debug: () => localStorage.getItem('debug') === 'true',
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`ccm19()` takes one rule per destination: the embedding with this id, an accepted cookie pattern, a function returning the answer, or `false` for a destination that needs no consent. It re-checks when the visitor closes the widget. For another cmp, write a `ConsentSource` of your own: `names`, `of(name)`, and optionally `free` and `watch(notify)`. An answer of `undefined` means the cmp has not read the stored choice yet, so events wait instead of being dropped.
|
|
158
|
+
|
|
159
|
+
A destination is a `name`, a `send(payload, meta)` and optionally `ready()`. It only sees events that carry a payload under its name. The bus polls `ready()` briefly and re-checks on the source's `watch`; `notifyRelay()` from `@astroscope/relay/client` re-checks by hand.
|
|
160
|
+
|
|
161
|
+
```ts
|
|
162
|
+
import type { Destination } from '@astroscope/relay/client';
|
|
163
|
+
|
|
164
|
+
const crm: Destination<'crm'> = {
|
|
165
|
+
name: 'crm',
|
|
166
|
+
send: (event, meta) => sendToCrm(event, meta.id),
|
|
167
|
+
};
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
`debug` logs every tracked event as a collapsed console group: what came in and, per destination, the payload or why it got nothing.
|
|
171
|
+
|
|
172
|
+
## Reporting from the server
|
|
173
|
+
|
|
174
|
+
The bus writes the consented destination names into the `x-relay-consent` header of every same-origin `fetch`. The middleware reads it, and `track()` in an action, an endpoint or a page sends each consented server destination its payload. The call returns the event id, so the browser can fire its pixel under the same one.
|
|
175
|
+
|
|
176
|
+
```ts
|
|
177
|
+
// src/actions/index.ts
|
|
178
|
+
import { defineAction } from '@astroscope/node/guards';
|
|
179
|
+
import { track } from '@astroscope/relay/track';
|
|
180
|
+
import { z } from 'astro/zod';
|
|
181
|
+
import { newsletterEvent } from '../relay/events';
|
|
182
|
+
|
|
183
|
+
export const server = {
|
|
184
|
+
subscribe: defineAction({
|
|
185
|
+
input: z.object({ email: z.email() }),
|
|
186
|
+
handler: async ({ email }) => {
|
|
187
|
+
await subscribe(email);
|
|
188
|
+
|
|
189
|
+
return { eventId: track(newsletterEvent({ user: { email } })) };
|
|
190
|
+
},
|
|
191
|
+
}),
|
|
192
|
+
};
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
```tsx
|
|
196
|
+
// the island fires the pixels under the id the server used
|
|
197
|
+
const { data } = await actions.subscribe({ email });
|
|
198
|
+
|
|
199
|
+
track(newsletterEvent({ id: data.eventId, user: { email } }));
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Outside a request, without the header, or for an excluded request `track()` reports nothing and still returns the id. A plain html form post carries no header and reports nothing.
|
|
203
|
+
|
|
204
|
+
The server destinations are the registry `src/relay/server.ts`. It carries secrets, so the client build refuses to import it.
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
// src/relay/server.ts
|
|
208
|
+
import { openAiConversions } from '@astroscope/relay/openai/server';
|
|
209
|
+
import { defineRelayServer } from '@astroscope/relay/server';
|
|
210
|
+
import { Config } from '@/config';
|
|
211
|
+
|
|
212
|
+
export default defineRelayServer({
|
|
213
|
+
destinations: {
|
|
214
|
+
openai: openAiConversions({ apiKey: Config.openAi.apiKey, pixelId: Config.openAi.pixelId, integrationSource: 'my-site', countryCallingCode: '49' }),
|
|
215
|
+
},
|
|
216
|
+
exclude: (ctx) => ctx.locals.session.e2e,
|
|
217
|
+
});
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
A server destination is a `name` and a `send(payload, meta)`, where `meta` adds the request: client address, headers, a cookie accessor and the source url. Its consent is the flag of its own name in the header. The `consent` map overrides that per name: `false` for a first-party record, or a function over the record to share another destination's flag, `crm: (record) => record.ga4`. `relayConsent()` from `@astroscope/relay/server` gives the record to anything else. `exclude` takes astroscope's path patterns or a predicate over the request context. `hashUser` and the normalizers are exported for a destination that matches on identifiers.
|
|
221
|
+
|
|
222
|
+
## Destinations
|
|
223
|
+
|
|
224
|
+
| Entry | Builders | Destination |
|
|
225
|
+
| --------------------------------- | ------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
|
|
226
|
+
| `@astroscope/relay/ga4` | `ga4.viewItem()`, `ga4.purchase()`, … and `ga4.event(name, params)` | `ga4Tag()`: the google tag via `gtag('event', …)`; installs the queue stub, ready once the tag loaded |
|
|
227
|
+
| `@astroscope/relay/gtm` | `gtm.purchase(commerce, params?)`, … and `gtm.event(name, params)` | `gtmContainer()`: `dataLayer` pushes with `event_id`; consent is the container's own embedding |
|
|
228
|
+
| `@astroscope/relay/matomo` | `matomo.event()`, `matomo.siteSearch()`, `matomo.order()`, `matomo.calls(…)` | `matomoTracker()`: the `_paq` queue; a cookieless setup is `false` in the consent source |
|
|
229
|
+
| `@astroscope/relay/awin` | `awin.sale({ amount, orderRef, currency, voucher?, parts? })` | `awinMastertag({ advertiserId, testMode? })`: declares `AWIN.Tracking.Sale` and fires the fall-back pixel |
|
|
230
|
+
| `@astroscope/relay/openai` | `openai.contentsViewed()`, `itemsAdded()`, `checkoutStarted()`, `orderCreated()`, `leadCreated()` | `openAiPixel({ countryCallingCode? })`: the openai ads pixel, identifiers hashed and sent through `init` |
|
|
231
|
+
| `@astroscope/relay/openai/server` | the same builders | `openAiConversions({ apiKey, pixelId, integrationSource, countryCallingCode? })`: the conversions api |
|
|
232
|
+
|
|
233
|
+
A destination of your own follows the same shape: builders for the payload, a browser destination, a server destination, all under one name. `wellKnownEvents(create)` from the root entry makes a builder set of the well-known events.
|
|
234
|
+
|
|
235
|
+
## License
|
|
236
|
+
|
|
237
|
+
MIT
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { a as Destination } from "../bus-Z7l8oJtS.js";
|
|
2
|
+
/** the sale as the mastertag declares it under `AWIN.Tracking.Sale` */
|
|
3
|
+
export type AwinSale = {
|
|
4
|
+
/** the order total with two decimals */
|
|
5
|
+
amount: string;
|
|
6
|
+
orderRef: string;
|
|
7
|
+
/** the commission groups and their amounts: `GROUP:amount|GROUP:amount` */
|
|
8
|
+
parts: string;
|
|
9
|
+
currency: string;
|
|
10
|
+
/** the voucher code used, or empty */
|
|
11
|
+
voucher: string;
|
|
12
|
+
};
|
|
13
|
+
declare module '@astroscope/relay' {
|
|
14
|
+
interface RelayDestinations {
|
|
15
|
+
awin: AwinSale;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export type AwinSaleParams = {
|
|
19
|
+
/** the order total */
|
|
20
|
+
amount: number;
|
|
21
|
+
orderRef: string;
|
|
22
|
+
currency: string;
|
|
23
|
+
voucher?: string | undefined;
|
|
24
|
+
/** the amount per commission group; default: the whole amount under `DEFAULT` */
|
|
25
|
+
parts?: Readonly<Record<string, number>> | undefined;
|
|
26
|
+
};
|
|
27
|
+
/** The awin builders: the sale an event definition puts under `awin`. */
|
|
28
|
+
export declare const awin: {
|
|
29
|
+
sale: ({ amount, orderRef, currency, voucher, parts }: AwinSaleParams) => AwinSale;
|
|
30
|
+
};
|
|
31
|
+
type DeclaredSale = AwinSale & {
|
|
32
|
+
channel: 'aw';
|
|
33
|
+
test: '0' | '1';
|
|
34
|
+
};
|
|
35
|
+
declare global {
|
|
36
|
+
interface Window {
|
|
37
|
+
AWIN?: {
|
|
38
|
+
Tracking?: {
|
|
39
|
+
Sale?: DeclaredSale;
|
|
40
|
+
run?: () => void;
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export type AwinMastertagOptions = {
|
|
46
|
+
advertiserId: string;
|
|
47
|
+
/** declare and fire the sales as test sales; default false */
|
|
48
|
+
testMode?: boolean | undefined;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* The awin mastertag as a destination: the sale is declared under `AWIN.Tracking.Sale` for the
|
|
52
|
+
* mastertag (loaded by the cmp after consent, it parses the declaration when it loads, or is told
|
|
53
|
+
* to run when it is there already) and the fall-back pixel is fired right away.
|
|
54
|
+
*/
|
|
55
|
+
export declare function awinMastertag(options: AwinMastertagOptions): Destination<'awin'>;
|
|
56
|
+
export {};
|
|
57
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/awin/index.ts"],"mappings":";;YAGY;;EAEV;EACA;;EAEA;EACA;;EAEA;;;YAIU;IACR,MAAM;;;YAIE;;EAEV;EACA;EACA;EACA;;EAEA,QAAQ,SAAS;;;qBAIN;EAC4C,SAAA,QAAA,UAAA,UAAA,SAAA,SAAA,mBAAiB;;KAWrE,eAAe;EAClB;EACA;;QAGM;YACI;IACR;MACE;QACE,OAAO;QACP;;;;;YAMI;EACV;;EAEA;;;;;;;wBAQc,cAAc,SAAS,uBAAuB"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/awin/index.ts
|
|
2
|
+
/** The awin builders: the sale an event definition puts under `awin`. */
|
|
3
|
+
const awin = { sale: ({ amount, orderRef, currency, voucher, parts }) => ({
|
|
4
|
+
amount: amount.toFixed(2),
|
|
5
|
+
orderRef,
|
|
6
|
+
parts: Object.entries(parts ?? { DEFAULT: amount }).map(([group, value]) => `${group}:${value.toFixed(2)}`).join("|"),
|
|
7
|
+
currency,
|
|
8
|
+
voucher: voucher ?? ""
|
|
9
|
+
}) };
|
|
10
|
+
/**
|
|
11
|
+
* The awin mastertag as a destination: the sale is declared under `AWIN.Tracking.Sale` for the
|
|
12
|
+
* mastertag (loaded by the cmp after consent, it parses the declaration when it loads, or is told
|
|
13
|
+
* to run when it is there already) and the fall-back pixel is fired right away.
|
|
14
|
+
*/
|
|
15
|
+
function awinMastertag(options) {
|
|
16
|
+
const { advertiserId, testMode = false } = options;
|
|
17
|
+
return {
|
|
18
|
+
name: "awin",
|
|
19
|
+
send: (sale) => {
|
|
20
|
+
const declared = {
|
|
21
|
+
...sale,
|
|
22
|
+
channel: "aw",
|
|
23
|
+
test: testMode ? "1" : "0"
|
|
24
|
+
};
|
|
25
|
+
declareSale(declared);
|
|
26
|
+
fireFallbackPixel(advertiserId, declared);
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function declareSale(sale) {
|
|
31
|
+
globalThis.window.AWIN ??= {};
|
|
32
|
+
globalThis.window.AWIN.Tracking ??= {};
|
|
33
|
+
globalThis.window.AWIN.Tracking.Sale = sale;
|
|
34
|
+
globalThis.window.AWIN.Tracking.run?.();
|
|
35
|
+
}
|
|
36
|
+
function fireFallbackPixel(advertiserId, sale) {
|
|
37
|
+
const params = new URLSearchParams({
|
|
38
|
+
tt: "ns",
|
|
39
|
+
tv: "2",
|
|
40
|
+
merchant: advertiserId,
|
|
41
|
+
amount: sale.amount,
|
|
42
|
+
ch: sale.channel,
|
|
43
|
+
parts: sale.parts,
|
|
44
|
+
ref: sale.orderRef,
|
|
45
|
+
cr: sale.currency,
|
|
46
|
+
vc: sale.voucher,
|
|
47
|
+
testmode: sale.test
|
|
48
|
+
});
|
|
49
|
+
const pixel = new Image(0, 0);
|
|
50
|
+
pixel.src = `https://www.awin1.com/sread.img?${params.toString()}`;
|
|
51
|
+
}
|
|
52
|
+
export { awin, awinMastertag };
|
|
53
|
+
|
|
54
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/awin/index.ts"],"sourcesContent":["import type { Destination } from '../client/bus.js';\n\n/** the sale as the mastertag declares it under `AWIN.Tracking.Sale` */\nexport type AwinSale = {\n /** the order total with two decimals */\n amount: string;\n orderRef: string;\n /** the commission groups and their amounts: `GROUP:amount|GROUP:amount` */\n parts: string;\n currency: string;\n /** the voucher code used, or empty */\n voucher: string;\n};\n\ndeclare module '@astroscope/relay' {\n interface RelayDestinations {\n awin: AwinSale;\n }\n}\n\nexport type AwinSaleParams = {\n /** the order total */\n amount: number;\n orderRef: string;\n currency: string;\n voucher?: string | undefined;\n /** the amount per commission group; default: the whole amount under `DEFAULT` */\n parts?: Readonly<Record<string, number>> | undefined;\n};\n\n/** The awin builders: the sale an event definition puts under `awin`. */\nexport const awin = {\n sale: ({ amount, orderRef, currency, voucher, parts }: AwinSaleParams): AwinSale => ({\n amount: amount.toFixed(2),\n orderRef,\n parts: Object.entries(parts ?? { DEFAULT: amount })\n .map(([group, value]) => `${group}:${value.toFixed(2)}`)\n .join('|'),\n currency,\n voucher: voucher ?? '',\n }),\n};\n\ntype DeclaredSale = AwinSale & {\n channel: 'aw';\n test: '0' | '1';\n};\n\ndeclare global {\n interface Window {\n AWIN?: {\n Tracking?: {\n Sale?: DeclaredSale;\n run?: () => void;\n };\n };\n }\n}\n\nexport type AwinMastertagOptions = {\n advertiserId: string;\n /** declare and fire the sales as test sales; default false */\n testMode?: boolean | undefined;\n};\n\n/**\n * The awin mastertag as a destination: the sale is declared under `AWIN.Tracking.Sale` for the\n * mastertag (loaded by the cmp after consent, it parses the declaration when it loads, or is told\n * to run when it is there already) and the fall-back pixel is fired right away.\n */\nexport function awinMastertag(options: AwinMastertagOptions): Destination<'awin'> {\n const { advertiserId, testMode = false } = options;\n\n return {\n name: 'awin',\n send: (sale) => {\n const declared: DeclaredSale = { ...sale, channel: 'aw', test: testMode ? '1' : '0' };\n\n declareSale(declared);\n fireFallbackPixel(advertiserId, declared);\n },\n };\n}\n\nfunction declareSale(sale: DeclaredSale): void {\n globalThis.window.AWIN ??= {};\n globalThis.window.AWIN.Tracking ??= {};\n globalThis.window.AWIN.Tracking.Sale = sale;\n\n globalThis.window.AWIN.Tracking.run?.();\n}\n\nfunction fireFallbackPixel(advertiserId: string, sale: DeclaredSale): void {\n const params = new URLSearchParams({\n tt: 'ns',\n tv: '2',\n merchant: advertiserId,\n amount: sale.amount,\n ch: sale.channel,\n parts: sale.parts,\n ref: sale.orderRef,\n cr: sale.currency,\n vc: sale.voucher,\n testmode: sale.test,\n });\n\n const pixel = new Image(0, 0);\n\n pixel.src = `https://www.awin1.com/sread.img?${params.toString()}`;\n}\n"],"mappings":";;AA+BA,MAAa,OAAO,EAClB,OAAO,EAAE,QAAQ,UAAU,UAAU,SAAS,aAAuC;CACnF,QAAQ,OAAO,QAAQ,CAAC;CACxB;CACA,OAAO,OAAO,QAAQ,SAAS,EAAE,SAAS,OAAO,CAAC,CAAC,CAChD,KAAK,CAAC,OAAO,WAAW,GAAG,MAAM,GAAG,MAAM,QAAQ,CAAC,GAAG,CAAC,CACvD,KAAK,GAAG;CACX;CACA,SAAS,WAAW;AACtB,GACF;;;;;;AA6BA,SAAgB,cAAc,SAAoD;CAChF,MAAM,EAAE,cAAc,WAAW,UAAU;CAE3C,OAAO;EACL,MAAM;EACN,OAAO,SAAS;GACd,MAAM,WAAyB;IAAE,GAAG;IAAM,SAAS;IAAM,MAAM,WAAW,MAAM;GAAI;GAEpF,YAAY,QAAQ;GACpB,kBAAkB,cAAc,QAAQ;EAC1C;CACF;AACF;AAEA,SAAS,YAAY,MAA0B;CAC7C,WAAW,OAAO,SAAS,CAAC;CAC5B,WAAW,OAAO,KAAK,aAAa,CAAC;CACrC,WAAW,OAAO,KAAK,SAAS,OAAO;CAEvC,WAAW,OAAO,KAAK,SAAS,MAAM;AACxC;AAEA,SAAS,kBAAkB,cAAsB,MAA0B;CACzE,MAAM,SAAS,IAAI,gBAAgB;EACjC,IAAI;EACJ,IAAI;EACJ,UAAU;EACV,QAAQ,KAAK;EACb,IAAI,KAAK;EACT,OAAO,KAAK;EACZ,KAAK,KAAK;EACV,IAAI,KAAK;EACT,IAAI,KAAK;EACT,UAAU,KAAK;CACjB,CAAC;CAED,MAAM,QAAQ,IAAI,MAAM,GAAG,CAAC;CAE5B,MAAM,MAAM,mCAAmC,OAAO,SAAS;AACjE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { i as DestinationName, l as RelayDestinations, n as ConsentRecord, p as TrackInput, r as ConsentSource, s as EventMeta, t as ConsentAnswer } from "./shared-CSwqcxPI.js";
|
|
2
|
+
/** one consumer of the bus: a tag, a pixel, a tracker, a log — it takes the payload built for it */
|
|
3
|
+
type Destination<N extends DestinationName = DestinationName> = {
|
|
4
|
+
/** the destination's name: its key in every event and in the registration, its flag in the consent header */
|
|
5
|
+
name: N;
|
|
6
|
+
/** whether the destination's sdk is there to take events; default: always */
|
|
7
|
+
ready?: (() => boolean) | undefined;
|
|
8
|
+
send: (payload: RelayDestinations[N], meta: EventMeta) => void;
|
|
9
|
+
};
|
|
10
|
+
/** a destination of any registered name */
|
|
11
|
+
type AnyDestination = { [N in DestinationName]: Destination<N>; }[DestinationName];
|
|
12
|
+
/** the destinations by name: the key an event's payload sits under, which is also the destination's own name */
|
|
13
|
+
type Destinations = { [N in DestinationName]?: Destination<N> | undefined; };
|
|
14
|
+
type RelayConfig<P extends Destinations = Destinations> = {
|
|
15
|
+
destinations: P;
|
|
16
|
+
/** the consent of exactly the registered destinations; `NoInfer` keeps `destinations` the only source of the names */
|
|
17
|
+
consent: ConsentSource<NoInfer<keyof P & string>>;
|
|
18
|
+
/**
|
|
19
|
+
* log every tracked event to the console, with what each destination got or why not; a function is asked per event
|
|
20
|
+
*/
|
|
21
|
+
debug?: boolean | (() => boolean) | undefined;
|
|
22
|
+
};
|
|
23
|
+
/** a consent source for whichever names: what the bus holds, as any `RelayConfig` narrows to it */
|
|
24
|
+
type ConsentHolder = Omit<ConsentSource, 'of'> & {
|
|
25
|
+
of: (name: never) => ConsentAnswer;
|
|
26
|
+
};
|
|
27
|
+
/** the configuration as the bus takes it, whichever names it was typed for */
|
|
28
|
+
type BusConfig = Omit<RelayConfig, 'consent'> & {
|
|
29
|
+
consent: ConsentHolder;
|
|
30
|
+
};
|
|
31
|
+
type Bus = {
|
|
32
|
+
/** register the destinations; events tracked earlier are delivered now */
|
|
33
|
+
configure: (config: BusConfig) => void;
|
|
34
|
+
/** put an event on the bus; returns its id */
|
|
35
|
+
track: (input: TrackInput) => string;
|
|
36
|
+
/** re-check the destinations' consent and readiness: after the cmp's choice changed or a destination sdk appeared */
|
|
37
|
+
notify: () => void;
|
|
38
|
+
/** the consent as known now, by destination name: what a request to the server carries */
|
|
39
|
+
consent: () => ConsentRecord;
|
|
40
|
+
};
|
|
41
|
+
type BusEnvironment = {
|
|
42
|
+
now?: (() => number) | undefined;
|
|
43
|
+
/** schedules a readiness re-check; returns the cancel */
|
|
44
|
+
schedule?: ((callback: () => void, ms: number) => () => void) | undefined;
|
|
45
|
+
};
|
|
46
|
+
declare function createBus(env?: BusEnvironment): Bus;
|
|
47
|
+
export { Destination as a, createBus as c, BusEnvironment as i, Bus as n, Destinations as o, BusConfig as r, RelayConfig as s, AnyDestination as t };
|
|
48
|
+
//# sourceMappingURL=bus-Z7l8oJtS.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bus-Z7l8oJtS.d.ts","names":[],"sources":["../src/client/bus.ts"],"mappings":";;KAiBY,YAAY,UAAU,kBAAkB;;EAElD,MAAM;;EAEN;EACA,OAAO,SAAS,kBAAkB,IAAI,MAAM;;;KAIlC,oBAAoB,KAAK,kBAAkB,YAAY,MAAK;;KAG5D,kBAAkB,KAAK,mBAAmB,YAAY;KAEtD,YAAY,UAAU,eAAe;EAC/C,cAAc;;EAEd,SAAS,cAAc,cAAc;;;;EAIrC;;;KAIG,gBAAgB,KAAK;EAAyB,KAAK,gBAAgB;;;KAG5D,YAAY,KAAK;EAA4B,SAAS;;KAEtD;;EAEV,YAAY,QAAQ;;EAEpB,QAAQ,OAAO;;EAEf;;EAEA,eAAe;;KAGL;EACV;;EAEA,aAAa,sBAAsB;;iBA0BrB,UAAU,MAAK,iBAAsB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { i as DestinationName, r as ConsentSource, t as ConsentAnswer } from "../shared-CSwqcxPI.js";
|
|
2
|
+
type Ccm19 = {
|
|
3
|
+
/** the accepted cookie name patterns, e.g. `_ga_*`; empty before a choice */
|
|
4
|
+
acceptedCookies?: readonly string[] | undefined;
|
|
5
|
+
/** the accepted embeddings; empty before a choice */
|
|
6
|
+
acceptedEmbeddings?: readonly {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
}[] | undefined;
|
|
10
|
+
};
|
|
11
|
+
declare global {
|
|
12
|
+
interface Window {
|
|
13
|
+
/** what ccm19 exposes once its script has run */
|
|
14
|
+
CCM?: Ccm19 | undefined;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* How a destination's consent is read from ccm19: the embedding with this id is accepted (a missing id
|
|
19
|
+
* never is), an accepted cookie pattern matches, an answer of your own, or `false` for a destination
|
|
20
|
+
* that needs none.
|
|
21
|
+
*/
|
|
22
|
+
export type Ccm19Rule = (() => ConsentAnswer) | false | {
|
|
23
|
+
embedding: string | undefined;
|
|
24
|
+
} | {
|
|
25
|
+
cookie: (pattern: string) => boolean;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* The consent source over ccm19: a rule per destination, `undefined` until ccm19 has run, re-checked
|
|
29
|
+
* when the visitor closes the widget.
|
|
30
|
+
*/
|
|
31
|
+
export declare function ccm19<N extends DestinationName>(rules: { [K in N]: Ccm19Rule; }): ConsentSource<N>;
|
|
32
|
+
export {};
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/ccm19/index.ts"],"mappings":";KAEK;;EAEH;;EAEA;IAAgC;IAAY;;;QAGtC;YACI;;IAER,MAAM;;;;;;;;YASE,mBACD;EAEL;;EACA,SAAS;;;;;;wBAyBC,MAAM,UAAU,iBAAiB,UAAU,KAAK,IAAI,eAAc,cAAc"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// src/ccm19/index.ts
|
|
2
|
+
const ccm = () => globalThis.window.CCM;
|
|
3
|
+
function answer(rule) {
|
|
4
|
+
if (rule === false) return true;
|
|
5
|
+
if (typeof rule === "function") return rule();
|
|
6
|
+
const current = ccm();
|
|
7
|
+
if ("embedding" in rule) {
|
|
8
|
+
const embeddings = current?.acceptedEmbeddings;
|
|
9
|
+
if (!embeddings) return void 0;
|
|
10
|
+
return rule.embedding !== void 0 && embeddings.some((embedding) => embedding.id === rule.embedding);
|
|
11
|
+
}
|
|
12
|
+
return current?.acceptedCookies?.some((pattern) => rule.cookie(pattern));
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The consent source over ccm19: a rule per destination, `undefined` until ccm19 has run, re-checked
|
|
16
|
+
* when the visitor closes the widget.
|
|
17
|
+
*/
|
|
18
|
+
function ccm19(rules) {
|
|
19
|
+
const entries = Object.entries(rules);
|
|
20
|
+
return {
|
|
21
|
+
names: entries.map(([name]) => name),
|
|
22
|
+
free: entries.filter(([, rule]) => rule === false).map(([name]) => name),
|
|
23
|
+
of: (name) => answer(rules[name]),
|
|
24
|
+
watch: (notify) => globalThis.window.addEventListener("ccm19WidgetClosed", notify)
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
export { ccm19 };
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/ccm19/index.ts"],"sourcesContent":["import type { ConsentAnswer, ConsentSource, DestinationName } from '../shared.js';\n\ntype Ccm19 = {\n /** the accepted cookie name patterns, e.g. `_ga_*`; empty before a choice */\n acceptedCookies?: readonly string[] | undefined;\n /** the accepted embeddings; empty before a choice */\n acceptedEmbeddings?: readonly { id: string; name: string }[] | undefined;\n};\n\ndeclare global {\n interface Window {\n /** what ccm19 exposes once its script has run */\n CCM?: Ccm19 | undefined;\n }\n}\n\n/**\n * How a destination's consent is read from ccm19: the embedding with this id is accepted (a missing id\n * never is), an accepted cookie pattern matches, an answer of your own, or `false` for a destination\n * that needs none.\n */\nexport type Ccm19Rule =\n | (() => ConsentAnswer)\n | false\n | { embedding: string | undefined }\n | { cookie: (pattern: string) => boolean };\n\nconst ccm = (): Ccm19 | undefined => globalThis.window.CCM;\n\nfunction answer(rule: Ccm19Rule): ConsentAnswer {\n if (rule === false) return true;\n if (typeof rule === 'function') return rule();\n\n const current = ccm();\n\n if ('embedding' in rule) {\n const embeddings = current?.acceptedEmbeddings;\n\n if (!embeddings) return undefined;\n\n return rule.embedding !== undefined && embeddings.some((embedding) => embedding.id === rule.embedding);\n }\n\n return current?.acceptedCookies?.some((pattern) => rule.cookie(pattern));\n}\n\n/**\n * The consent source over ccm19: a rule per destination, `undefined` until ccm19 has run, re-checked\n * when the visitor closes the widget.\n */\nexport function ccm19<N extends DestinationName>(rules: { [K in N]: Ccm19Rule }): ConsentSource<N> {\n const entries = Object.entries(rules) as [N, Ccm19Rule][];\n\n return {\n names: entries.map(([name]) => name),\n free: entries.filter(([, rule]) => rule === false).map(([name]) => name),\n of: (name) => answer(rules[name]),\n watch: (notify) => globalThis.window.addEventListener('ccm19WidgetClosed', notify),\n };\n}\n"],"mappings":";AA2BA,MAAM,YAA+B,WAAW,OAAO;AAEvD,SAAS,OAAO,MAAgC;CAC9C,IAAI,SAAS,OAAO,OAAO;CAC3B,IAAI,OAAO,SAAS,YAAY,OAAO,KAAK;CAE5C,MAAM,UAAU,IAAI;CAEpB,IAAI,eAAe,MAAM;EACvB,MAAM,aAAa,SAAS;EAE5B,IAAI,CAAC,YAAY,OAAO,KAAA;EAExB,OAAO,KAAK,cAAc,KAAA,KAAa,WAAW,MAAM,cAAc,UAAU,OAAO,KAAK,SAAS;CACvG;CAEA,OAAO,SAAS,iBAAiB,MAAM,YAAY,KAAK,OAAO,OAAO,CAAC;AACzE;;;;;AAMA,SAAgB,MAAiC,OAAkD;CACjG,MAAM,UAAU,OAAO,QAAQ,KAAK;CAEpC,OAAO;EACL,OAAO,QAAQ,KAAK,CAAC,UAAU,IAAI;EACnC,MAAM,QAAQ,QAAQ,GAAG,UAAU,SAAS,KAAK,CAAC,CAAC,KAAK,CAAC,UAAU,IAAI;EACvE,KAAK,SAAS,OAAO,MAAM,KAAK;EAChC,QAAQ,WAAW,WAAW,OAAO,iBAAiB,qBAAqB,MAAM;CACnF;AACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { a as Destination, c as createBus, i as BusEnvironment, n as Bus, o as Destinations, r as BusConfig, s as RelayConfig, t as AnyDestination } from "../bus-Z7l8oJtS.js";
|
|
2
|
+
/**
|
|
3
|
+
* Types the browser half: the default export of `src/relay/client.ts`, which the integration loads
|
|
4
|
+
* on every page and configures the bus with. A promise is awaited, for a setup that has to wait
|
|
5
|
+
* for something first.
|
|
6
|
+
*/
|
|
7
|
+
export declare function defineRelayClient<P extends Destinations>(config: RelayConfig<P> | Promise<RelayConfig<P>>): RelayConfig<P> | Promise<RelayConfig<P>>;
|
|
8
|
+
/**
|
|
9
|
+
* Registers the destinations; events tracked earlier are delivered now. The integration does this with
|
|
10
|
+
* the client module's default export.
|
|
11
|
+
*/
|
|
12
|
+
export declare function configureRelay<P extends Destinations>(config: RelayConfig<P>): void;
|
|
13
|
+
/** re-checks the destinations' consent and readiness: after the cmp's choice changed or a destination sdk appeared */
|
|
14
|
+
export declare function notifyRelay(): void;
|
|
15
|
+
export { type AnyDestination, type Bus, type BusConfig, type BusEnvironment, type Destination, type Destinations, type RelayConfig, createBus };
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/client/index.ts"],"mappings":";;;;;;wBAWgB,kBAAkB,UAAU,cAC1C,QAAQ,YAAY,KAAK,QAAQ,YAAY,MAC5C,YAAY,KAAK,QAAQ,YAAY;;;;;wBAQxB,eAAe,UAAU,cAAc,QAAQ,YAAY;;wBAK3D"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { n as createBus, t as bus } from "../instance-Bu0EMJ_-.js";
|
|
2
|
+
// src/client/index.ts
|
|
3
|
+
/**
|
|
4
|
+
* Types the browser half: the default export of `src/relay/client.ts`, which the integration loads
|
|
5
|
+
* on every page and configures the bus with. A promise is awaited, for a setup that has to wait
|
|
6
|
+
* for something first.
|
|
7
|
+
*/
|
|
8
|
+
function defineRelayClient(config) {
|
|
9
|
+
return config;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Registers the destinations; events tracked earlier are delivered now. The integration does this with
|
|
13
|
+
* the client module's default export.
|
|
14
|
+
*/
|
|
15
|
+
function configureRelay(config) {
|
|
16
|
+
bus.configure(config);
|
|
17
|
+
}
|
|
18
|
+
/** re-checks the destinations' consent and readiness: after the cmp's choice changed or a destination sdk appeared */
|
|
19
|
+
function notifyRelay() {
|
|
20
|
+
bus.notify();
|
|
21
|
+
}
|
|
22
|
+
export { configureRelay, createBus, defineRelayClient, notifyRelay };
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/client/index.ts"],"sourcesContent":["import type { Destinations, RelayConfig } from './bus.js';\nimport { bus } from './instance.js';\n\nexport type { AnyDestination, Bus, BusConfig, BusEnvironment, Destination, Destinations, RelayConfig } from './bus.js';\nexport { createBus } from './bus.js';\n\n/**\n * Types the browser half: the default export of `src/relay/client.ts`, which the integration loads\n * on every page and configures the bus with. A promise is awaited, for a setup that has to wait\n * for something first.\n */\nexport function defineRelayClient<P extends Destinations>(\n config: RelayConfig<P> | Promise<RelayConfig<P>>,\n): RelayConfig<P> | Promise<RelayConfig<P>> {\n return config;\n}\n\n/**\n * Registers the destinations; events tracked earlier are delivered now. The integration does this with\n * the client module's default export.\n */\nexport function configureRelay<P extends Destinations>(config: RelayConfig<P>): void {\n bus.configure(config);\n}\n\n/** re-checks the destinations' consent and readiness: after the cmp's choice changed or a destination sdk appeared */\nexport function notifyRelay(): void {\n bus.notify();\n}\n"],"mappings":";;;;;;;AAWA,SAAgB,kBACd,QAC0C;CAC1C,OAAO;AACT;;;;;AAMA,SAAgB,eAAuC,QAA8B;CACnF,IAAI,UAAU,MAAM;AACtB;;AAGA,SAAgB,cAAoB;CAClC,IAAI,OAAO;AACb"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track.d.ts","names":[],"sources":["../../src/client/track.ts"],"mappings":";;qBAIa,OAAO"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { t as bus } from "../instance-Bu0EMJ_-.js";
|
|
2
|
+
// src/client/track.ts
|
|
3
|
+
/** records that something happened: the event, with the payloads of the destinations it is meant for; returns its id */
|
|
4
|
+
const track = (input) => bus.track(input);
|
|
5
|
+
export { track };
|
|
6
|
+
|
|
7
|
+
//# sourceMappingURL=track.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"track.js","names":[],"sources":["../../src/client/track.ts"],"sourcesContent":["import type { TrackFunction } from '../shared.js';\nimport { bus } from './instance.js';\n\n/** records that something happened: the event, with the payloads of the destinations it is meant for; returns its id */\nexport const track: TrackFunction = (input) => bus.track(input);\n"],"mappings":";;;AAIA,MAAa,SAAwB,UAAU,IAAI,MAAM,KAAK"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { p as TrackInput } from "./shared-CSwqcxPI.js";
|
|
2
|
+
/**
|
|
3
|
+
* The body of an inline script that tracks an event from hand-written html, before or after the
|
|
4
|
+
* bus is installed; `<Track>` is the same thing as an Astro component.
|
|
5
|
+
*/
|
|
6
|
+
declare function inlineTrack(input: TrackInput): string;
|
|
7
|
+
/** a collector's options; the context identifies the batch and is handed back with it */
|
|
8
|
+
type CollectOptions<Ctx, Item> = {
|
|
9
|
+
/** takes one batch: the context of its first sighting and the items collected under that key */
|
|
10
|
+
flush: (context: Ctx, items: Item[]) => void;
|
|
11
|
+
/** the quiet time after the last sighting before the batch goes out, in ms; default 500 */
|
|
12
|
+
within?: number | undefined;
|
|
13
|
+
/** the items a batch carries at most, 1 or more; a fuller buffer goes out as several batches; default unlimited */
|
|
14
|
+
max?: number | undefined;
|
|
15
|
+
};
|
|
16
|
+
/** a string context is its own key; any other context needs a key function */
|
|
17
|
+
type KeyOption<Ctx> = Ctx extends string ? {
|
|
18
|
+
key?: ((context: Ctx) => string) | undefined;
|
|
19
|
+
} : {
|
|
20
|
+
key: (context: Ctx) => string;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Folds single sightings into batched events: a list of items is seen one item at a time as the
|
|
24
|
+
* rows enter the viewport, while `view_item_list` is one event with the items. The collector
|
|
25
|
+
* keeps a buffer per key and flushes it after the quiet time, in chunks of at most `max` items.
|
|
26
|
+
* Buffers are shared by every caller of the collector, so sightings with the same key from
|
|
27
|
+
* several components go out as one batch.
|
|
28
|
+
*/
|
|
29
|
+
declare function collect<Ctx, Item>(options: CollectOptions<Ctx, Item> & KeyOption<Ctx>): (context: Ctx, item: Item) => void;
|
|
30
|
+
export { collect as n, inlineTrack as r, CollectOptions as t };
|
|
31
|
+
//# sourceMappingURL=collect-DRl177oR.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collect-DRl177oR.d.ts","names":[],"sources":["../src/inline.ts","../src/collect.ts"],"mappings":";;;;;iBAMgB,YAAY,OAAO;;KCLvB,eAAe,KAAK;;EAE9B,QAAQ,SAAS,KAAK,OAAO;;EAE7B;;EAEA;;;KAIG,UAAU,OAAO;EAChB,QAAQ,SAAS;;EACjB,MAAM,SAAS;;;;;;;;;iBAiBL,QAAQ,KAAK,MAC3B,SAAS,eAAe,KAAK,QAAQ,UAAU,QAC7C,SAAS,KAAK,MAAM"}
|