@autobusal/providers 1.10.0 → 1.12.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/CHANGELOG.md +14 -0
- package/Setup/Setup.tsx +5 -1
- package/Setup/analytics.ts +69 -12
- package/package.json +1 -1
- package/types/routes.ts +10 -0
- package/types/settings.ts +29 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,20 @@ All notable changes to `@autobusal/providers` are documented here. This project
|
|
|
4
4
|
adheres to [Keep a Changelog](https://keepachangelog.com/en/1.1.0/) and
|
|
5
5
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
> Note: 1.8.0 through 1.11.0 were published without changelog entries. The
|
|
8
|
+
> gap is left as-is rather than reconstructed after the fact.
|
|
9
|
+
|
|
10
|
+
## [1.12.0] - 2026-08-01
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- `FoundData.stops_count` - intermediate stops between the searched from/to,
|
|
15
|
+
where 0 means a direct trip. Optional, because external-provider offers do
|
|
16
|
+
not report one: a filter must read "missing" as unknown, never as direct.
|
|
17
|
+
- `FoundData.priority` - the operator's subscription priority, which obtapi
|
|
18
|
+
was already sending but which was not typed. Used only as a tiebreak in
|
|
19
|
+
routes-order's "recommended" ordering.
|
|
20
|
+
|
|
7
21
|
## [1.7.0] - 2026-07-31
|
|
8
22
|
|
|
9
23
|
### Added
|
package/Setup/Setup.tsx
CHANGED
|
@@ -17,7 +17,11 @@ const Setup = ({ type, children }: Props): JSX.Element => {
|
|
|
17
17
|
|
|
18
18
|
languages(type, data.preferences.languages.default);
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
// Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
21
|
+
// The brand's GTM container, from labels_settings via the admin GUI.
|
|
22
|
+
// obtapi sends `analytics` only when it is switched on AND configured, so
|
|
23
|
+
// this is a single truthy check with nothing to keep in sync.
|
|
24
|
+
analytics(data.analytics?.gtm_id);
|
|
21
25
|
|
|
22
26
|
return (
|
|
23
27
|
<Preload data={ data }>
|
package/Setup/analytics.ts
CHANGED
|
@@ -1,18 +1,75 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Google Tag Manager, loaded per brand from the label's own settings.
|
|
3
|
+
*
|
|
4
|
+
* Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
5
|
+
*
|
|
6
|
+
* This replaced a direct GA4 (react-ga4) integration driven by
|
|
7
|
+
* `preferences.googleAnalyticsID`, which lived in each brand's static
|
|
8
|
+
* settings.json on disk - not in the database, with no admin screen, so
|
|
9
|
+
* changing it meant editing a file on the server. It was unset on every
|
|
10
|
+
* brand, so nothing was actually being measured.
|
|
11
|
+
*
|
|
12
|
+
* GTM instead, for the reason GTM exists: GA4, Ads and anything added later
|
|
13
|
+
* are configured in the container, so a new tag never needs a code change or
|
|
14
|
+
* a deploy. Nothing in this codebase should know which tags a brand runs.
|
|
15
|
+
*
|
|
16
|
+
* The dataLayer is created BEFORE the container script loads. GTM reads
|
|
17
|
+
* whatever is already queued there when it initialises, so anything pushed
|
|
18
|
+
* in the meantime - the first page_view, most importantly - survives the
|
|
19
|
+
* race with the network rather than being dropped.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
declare global {
|
|
23
|
+
interface Window {
|
|
24
|
+
dataLayer?: Record<string, any>[]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const CONTAINER_ID = 'gtm-container';
|
|
29
|
+
|
|
30
|
+
const analytics = (container: string | null | undefined): void => {
|
|
31
|
+
if (!container) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Guard against a second insert. Two containers on one page double-count
|
|
36
|
+
// every tag they fire, and Setup can re-run (a settings refetch, a
|
|
37
|
+
// remount) without the page ever reloading.
|
|
38
|
+
if (document.getElementById(CONTAINER_ID)) {
|
|
12
39
|
return;
|
|
13
40
|
}
|
|
14
41
|
|
|
15
|
-
|
|
42
|
+
window.dataLayer = window.dataLayer || [];
|
|
43
|
+
window.dataLayer.push({ 'gtm.start': Date.now(), event: 'gtm.js' });
|
|
44
|
+
|
|
45
|
+
const script = document.createElement('script');
|
|
46
|
+
|
|
47
|
+
script.id = CONTAINER_ID;
|
|
48
|
+
script.async = true;
|
|
49
|
+
script.src = `https://www.googletagmanager.com/gtm.js?id=${ encodeURIComponent(container) }`;
|
|
50
|
+
|
|
51
|
+
document.head.appendChild(script);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Announce a page view.
|
|
56
|
+
*
|
|
57
|
+
* A single-page app never reloads, so GTM's own page-load trigger fires
|
|
58
|
+
* exactly once per session - every client-side route change after that is
|
|
59
|
+
* invisible unless it is announced. The container is expected to listen for
|
|
60
|
+
* this `page_view` event and fire GA4 (or anything else) from it.
|
|
61
|
+
*
|
|
62
|
+
* Safe to call before GTM has finished loading: the push simply queues.
|
|
63
|
+
*/
|
|
64
|
+
export const pageview = (path: string, title: string): void => {
|
|
65
|
+
window.dataLayer = window.dataLayer || [];
|
|
66
|
+
|
|
67
|
+
window.dataLayer.push({
|
|
68
|
+
event: 'page_view',
|
|
69
|
+
page_path: path,
|
|
70
|
+
page_title: title,
|
|
71
|
+
page_location: window.location.href
|
|
72
|
+
});
|
|
16
73
|
};
|
|
17
74
|
|
|
18
75
|
export default analytics;
|
package/package.json
CHANGED
package/types/routes.ts
CHANGED
|
@@ -91,6 +91,16 @@ export interface FoundData extends Omit<RouteData, 'locations' | 'id'> {
|
|
|
91
91
|
// still assume a real numeric local id.
|
|
92
92
|
price: Omit<PriceData, 'id'> & { id: number | string }
|
|
93
93
|
duration: string
|
|
94
|
+
// Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
95
|
+
// Intermediate stops between the searched from/to - 0 is a direct trip.
|
|
96
|
+
// Optional because external-provider offers don't report one; a filter
|
|
97
|
+
// must read "missing" as unknown, never as direct.
|
|
98
|
+
stops_count?: number
|
|
99
|
+
// Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
100
|
+
// The operator's subscription priority, as obtapi already sends it.
|
|
101
|
+
// Used only as a tiebreak in the "recommended" ordering - see
|
|
102
|
+
// routes-order's Found/refine.ts. Absent on external-provider offers.
|
|
103
|
+
priority?: number
|
|
94
104
|
customs: string[]
|
|
95
105
|
locations: {
|
|
96
106
|
from: LocationData
|
package/types/settings.ts
CHANGED
|
@@ -8,6 +8,14 @@ export interface SettingsData {
|
|
|
8
8
|
construction?: {
|
|
9
9
|
title: string
|
|
10
10
|
message: string
|
|
11
|
+
} | null
|
|
12
|
+
|
|
13
|
+
// Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
14
|
+
// The brand's Google Tag Manager container, managed from the admin GUI.
|
|
15
|
+
// Present ONLY when analytics is switched on and a container is actually
|
|
16
|
+
// configured, so its presence is the switch. Replaces the old
|
|
17
|
+
// preferences.googleAnalyticsID, which lived in a static file on disk.
|
|
18
|
+
analytics?: {
|
|
11
19
|
gtm_id: string
|
|
12
20
|
} | null
|
|
13
21
|
|
|
@@ -41,7 +49,10 @@ export interface SettingsData {
|
|
|
41
49
|
preferences: {
|
|
42
50
|
company: string
|
|
43
51
|
|
|
44
|
-
|
|
52
|
+
/** @deprecated Replaced by the admin-managed GTM container - see
|
|
53
|
+
* `analytics` above. Nothing reads this any more; it remains only
|
|
54
|
+
* because it is still present in older brands' settings.json files. */
|
|
55
|
+
googleAnalyticsID?: string | null
|
|
45
56
|
bookingID?: string
|
|
46
57
|
|
|
47
58
|
operatorId?: number
|
|
@@ -231,6 +242,23 @@ export interface LabelSettings {
|
|
|
231
242
|
description?: string
|
|
232
243
|
keywords?: string
|
|
233
244
|
}
|
|
245
|
+
|
|
246
|
+
// Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
247
|
+
// Admin-managed Google Tag Manager container. The PUBLIC settings payload
|
|
248
|
+
// exposes only the id, and only while enabled - see
|
|
249
|
+
// Labels\AdminController::analytics().
|
|
250
|
+
analytics?: {
|
|
251
|
+
enabled?: boolean
|
|
252
|
+
gtm_id?: string
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Edited: Ferjolt Ozuni - Date: 2026-08-01
|
|
256
|
+
// Admin-managed under-construction holding page.
|
|
257
|
+
construction?: {
|
|
258
|
+
enabled?: boolean
|
|
259
|
+
title?: string
|
|
260
|
+
message?: string
|
|
261
|
+
}
|
|
234
262
|
}
|
|
235
263
|
|
|
236
264
|
// Edited: Ferjolt Ozuni - Date: 2026-07-18
|