@healthya-team/pharmacy-analytics 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 +243 -2
- package/dist/client/index.d.mts +215 -0
- package/dist/client/index.d.ts +215 -0
- package/dist/client/index.js +218 -0
- package/dist/client/index.mjs +161 -0
- package/dist/index.d.mts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +9391 -0
- package/dist/index.mjs +9359 -0
- package/dist/server/index.d.mts +21 -0
- package/dist/server/index.d.ts +21 -0
- package/dist/server/index.js +1011 -0
- package/dist/server/index.mjs +984 -0
- package/dist/studio/index.d.mts +393 -0
- package/dist/studio/index.d.ts +393 -0
- package/dist/studio/index.js +8222 -0
- package/dist/studio/index.mjs +8216 -0
- package/package.json +103 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Healthya Engineering Team
|
|
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,244 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @healthya-team/pharmacy-analytics
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **Unified Pharmacy Analytics Platform**
|
|
4
|
+
> Consolidates Google Analytics 4 (GA4), Mixpanel patient funnels, and Google Search Console into a single high-performance library with Next.js App Router handlers and a Sanity Studio dashboard.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 🌟 Key Features
|
|
9
|
+
|
|
10
|
+
1. **Centralized Tab Switcher (Center of the Page)**
|
|
11
|
+
- **All (Default)**: Consolidated executive overview combining Google Organic Search, visitor metrics, and patient pre-consultation & prescription order conversion funnels. Displays all three groups in the sidebar simultaneously (as in the Highfield package).
|
|
12
|
+
- **Analytics**: Dedicated Google Analytics 4 views (Overview, Traffic, Content, Audience, Geography, Events, Acquisition).
|
|
13
|
+
- **Custom Analytics**: Healthcare journey funnels (Pre-Consult funnel steps, drop-offs, PM Funnel, Conditions & Products overview).
|
|
14
|
+
- **Search Console**: Google organic search performance (Top queries, landing pages, rankings, devices, countries, search appearance, and sitemaps).
|
|
15
|
+
|
|
16
|
+
2. **Unified Google Cloud Auth**
|
|
17
|
+
- Single Google Service Account (`GA_SERVICE_ACCOUNT_EMAIL` + `GA_PRIVATE_KEY`) signs RS256 JWTs using `jose` with in-memory token caching.
|
|
18
|
+
- Authorizes both **GA4 Data API** (`analytics.readonly`) and **Google Search Console API** (`webmasters`).
|
|
19
|
+
|
|
20
|
+
3. **Subpath Exports**
|
|
21
|
+
- `@healthya-team/pharmacy-analytics/client`: Consent-aware GA4 script, Mixpanel initializer, route tracking provider, and typed healthcare event trackers.
|
|
22
|
+
- `@healthya-team/pharmacy-analytics/server`: Next.js App Router route handlers serving GA4 and Search Console.
|
|
23
|
+
- `@healthya-team/pharmacy-analytics/studio`: Sanity Studio plugin and standalone `<PharmacyAnalyticsDashboard />` component.
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 📦 Installation
|
|
28
|
+
|
|
29
|
+
In your Next.js and Sanity project:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# If linking locally or in a pnpm monorepo:
|
|
33
|
+
pnpm add @healthya-team/pharmacy-analytics
|
|
34
|
+
|
|
35
|
+
# Or using relative package reference:
|
|
36
|
+
# "dependencies": { "@healthya-team/pharmacy-analytics": "workspace:*" }
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## ⚙️ Environment Configuration
|
|
42
|
+
|
|
43
|
+
Add the following environment variables to your `.env.local`:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# ── Google Analytics 4 ──
|
|
47
|
+
NEXT_PUBLIC_GA_MEASUREMENT_ID=G-XXXXXXXXXX
|
|
48
|
+
GA_PROPERTY_ID=123456789
|
|
49
|
+
|
|
50
|
+
# ── Google Search Console ──
|
|
51
|
+
SEARCH_CONSOLE_SITE_URL=https://your-pharmacy-website.co.uk
|
|
52
|
+
|
|
53
|
+
# ── Google Service Account (Shared by GA4 & Search Console) ──
|
|
54
|
+
GA_SERVICE_ACCOUNT_EMAIL=pharmacy-analytics-sa@project.iam.gserviceaccount.com
|
|
55
|
+
GA_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC...\n-----END PRIVATE KEY-----\n"
|
|
56
|
+
|
|
57
|
+
# ── Mixpanel (Optional / Pre-Consult Funnels) ──
|
|
58
|
+
NEXT_PUBLIC_MIXPANEL_TOKEN=your_mixpanel_project_token
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
> **Note on Permissions:**
|
|
62
|
+
> - In **Google Analytics Admin → Property Access Management**, grant your service account email the **Viewer** role.
|
|
63
|
+
> - In **Google Search Console → Settings → Users and permissions**, add your service account email with **Full** or **Owner** permission.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 🚀 Usage
|
|
68
|
+
|
|
69
|
+
### 1. Unified Next.js API Route Handler
|
|
70
|
+
|
|
71
|
+
Create `app/api/analytics/route.ts` in your Next.js application:
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
// app/api/analytics/route.ts
|
|
75
|
+
export { GET, POST } from '@healthya-team/pharmacy-analytics/server'
|
|
76
|
+
|
|
77
|
+
export const dynamic = 'force-dynamic'
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
*That's it!* This single route automatically handles:
|
|
81
|
+
- GA4 multi-reports (`/api/analytics?range=30`)
|
|
82
|
+
- GA4 custom dimensions (`?mode=event-params`, `?mode=condition-values`, `?mode=top-entities`)
|
|
83
|
+
- Search Console queries (`?mode=search-console&range=28`)
|
|
84
|
+
- Search Console sitemap submissions via `POST`
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
### 2. Client-Side Tracking & Providers
|
|
89
|
+
|
|
90
|
+
Add the tracking provider to your root layout (`app/layout.tsx`):
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
// app/layout.tsx
|
|
94
|
+
import {
|
|
95
|
+
AnalyticsProvider,
|
|
96
|
+
GaScript,
|
|
97
|
+
MixpanelInit,
|
|
98
|
+
} from '@healthya-team/pharmacy-analytics/client'
|
|
99
|
+
|
|
100
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
101
|
+
return (
|
|
102
|
+
<html lang="en">
|
|
103
|
+
<head>
|
|
104
|
+
<GaScript defaultConsent="denied" />
|
|
105
|
+
<MixpanelInit />
|
|
106
|
+
</head>
|
|
107
|
+
<body>
|
|
108
|
+
<AnalyticsProvider>
|
|
109
|
+
{children}
|
|
110
|
+
</AnalyticsProvider>
|
|
111
|
+
</body>
|
|
112
|
+
</html>
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
#### Firing Healthcare & Pharmacy Events:
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import {
|
|
121
|
+
trackConditionViewed,
|
|
122
|
+
trackEligibilityChecked,
|
|
123
|
+
trackStartAssessmentClicked,
|
|
124
|
+
trackQuestionnaireFlowStep,
|
|
125
|
+
trackOrderSuccess,
|
|
126
|
+
} from '@healthya-team/pharmacy-analytics/client'
|
|
127
|
+
|
|
128
|
+
// When a patient views a clinical condition
|
|
129
|
+
trackConditionViewed('Weight Loss', 'weight-loss')
|
|
130
|
+
|
|
131
|
+
// When patient checks eligibility
|
|
132
|
+
trackEligibilityChecked({
|
|
133
|
+
conditionName: 'Weight Loss',
|
|
134
|
+
status: 'eligible',
|
|
135
|
+
isNhs: false,
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
// When patient clicks start assessment
|
|
139
|
+
trackStartAssessmentClicked('Weight Loss')
|
|
140
|
+
|
|
141
|
+
// When patient completes questionnaire step
|
|
142
|
+
trackQuestionnaireFlowStep({
|
|
143
|
+
step: 'questionnaire_submitted',
|
|
144
|
+
userJourneyFlow: 'appointment_booking',
|
|
145
|
+
conditionName: 'Weight Loss',
|
|
146
|
+
})
|
|
147
|
+
|
|
148
|
+
// When patient completes order
|
|
149
|
+
trackOrderSuccess({
|
|
150
|
+
orderId: 'ORD-12345',
|
|
151
|
+
productName: 'Mounjaro 2.5mg',
|
|
152
|
+
conditionName: 'Weight Loss',
|
|
153
|
+
total: 149.00,
|
|
154
|
+
})
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
### 3. Sanity Studio Dashboard Integration
|
|
160
|
+
|
|
161
|
+
Add the plugin to your `sanity.config.ts`:
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
// sanity.config.ts
|
|
165
|
+
import { defineConfig } from 'sanity'
|
|
166
|
+
import { pharmacyAnalyticsPlugin } from '@healthya-team/pharmacy-analytics/studio'
|
|
167
|
+
|
|
168
|
+
export default defineConfig({
|
|
169
|
+
name: 'default',
|
|
170
|
+
title: 'Pharmacy Studio',
|
|
171
|
+
projectId: 'your-project-id',
|
|
172
|
+
dataset: 'production',
|
|
173
|
+
plugins: [
|
|
174
|
+
pharmacyAnalyticsPlugin({
|
|
175
|
+
apiUrl: '/api/analytics',
|
|
176
|
+
title: 'Highfield Analytics',
|
|
177
|
+
}),
|
|
178
|
+
],
|
|
179
|
+
})
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
#### Or use the React component standalone:
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
import { PharmacyAnalyticsDashboard } from '@healthya-team/pharmacy-analytics/studio'
|
|
186
|
+
|
|
187
|
+
export default function AdminAnalyticsPage() {
|
|
188
|
+
return (
|
|
189
|
+
<PharmacyAnalyticsDashboard
|
|
190
|
+
apiUrl="/api/analytics"
|
|
191
|
+
brandName="Highfield Pharmacy"
|
|
192
|
+
/>
|
|
193
|
+
)
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 🖥️ Dashboard Architecture & Tab Navigation
|
|
200
|
+
|
|
201
|
+
```
|
|
202
|
+
┌────────────────────────────────────────────────────────────────────────────────────────┐
|
|
203
|
+
│ [H] Highfield Analytics [ All | Analytics | Custom Analytics | Search Console ] [7d|14d|30d|90d] [Refresh]│
|
|
204
|
+
├─────────────────────────┬──────────────────────────────────────────────────────────────┤
|
|
205
|
+
│ ▦ Executive Overview │ EXECUTIVE SUMMARY BANNER & LIVE ACTIVE VISITORS │
|
|
206
|
+
│ │ │
|
|
207
|
+
│ ▾ GOOGLE ANALYTICS │ KPIs: Organic Clicks | Impressions | Visitors | Pre-Consult │
|
|
208
|
+
│ ▦ Overview │ │
|
|
209
|
+
│ ↗ Traffic │ [Explore GA4] [Explore Funnels] [Explore Search] │
|
|
210
|
+
│ ≡ Content │ │
|
|
211
|
+
│ ◉ Audience │ CHARTS: │
|
|
212
|
+
│ ⊕ Geography │ • Google Search Daily Trend (Clicks & Impressions) │
|
|
213
|
+
│ ⚡ Events │ • Website Visitors & Sessions Daily Trend │
|
|
214
|
+
│ ⤴ Acquisition │ │
|
|
215
|
+
│ │ TABLES: │
|
|
216
|
+
│ ▾ CUSTOM ANALYTICS │ • Top Google Organic Queries (Clicks & Rankings) │
|
|
217
|
+
│ 🧬 Overview │ • Top Visited Pages (Views & Visitors) │
|
|
218
|
+
│ ⬡ Pre Consult Events │ │
|
|
219
|
+
│ 💊 PM Funnel Events │ │
|
|
220
|
+
│ │ │
|
|
221
|
+
│ ▾ SEARCH CONSOLE │ │
|
|
222
|
+
│ ◎ Overview │ │
|
|
223
|
+
│ 🔍 Top Queries │ │
|
|
224
|
+
│ 📄 Top Pages │ │
|
|
225
|
+
│ 🌐 Countries │ │
|
|
226
|
+
│ 📱 Devices │ │
|
|
227
|
+
│ ✨ Appearance │ │
|
|
228
|
+
│ 🗺️ Sitemaps │ │
|
|
229
|
+
└─────────────────────────┴──────────────────────────────────────────────────────────────┘
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## 🛠️ Build & Verification
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
# Type check without emitting
|
|
238
|
+
pnpm typecheck
|
|
239
|
+
|
|
240
|
+
# Build ESM & CJS bundles + d.ts files
|
|
241
|
+
pnpm build
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
Built with ❤️ by Healthya Engineering Team.
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import react__default from 'react';
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
interface Window {
|
|
5
|
+
gtag: (...args: unknown[]) => void;
|
|
6
|
+
dataLayer: unknown[];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Fires an analytics event to GA4 (via gtag) and Mixpanel in parallel.
|
|
11
|
+
* No-ops server-side. GA4 is skipped when gtag is unavailable (e.g. consent denied).
|
|
12
|
+
*/
|
|
13
|
+
declare function trackEvent(eventName: string, params?: Record<string, unknown>): void;
|
|
14
|
+
declare function trackPageView(pagePath: string, pageTitle: string): void;
|
|
15
|
+
interface ConditionTrackingParams {
|
|
16
|
+
condition_slug: string;
|
|
17
|
+
condition_name: string;
|
|
18
|
+
condition_id: string | number;
|
|
19
|
+
branch_corporate_id?: string | number;
|
|
20
|
+
source?: string;
|
|
21
|
+
is_pre_consult: boolean;
|
|
22
|
+
is_private_medication: boolean;
|
|
23
|
+
}
|
|
24
|
+
declare function trackConditionViewed(params: ConditionTrackingParams): void;
|
|
25
|
+
interface StartAssessmentClickedParams {
|
|
26
|
+
eligibility_status: 'passed' | 'failed';
|
|
27
|
+
is_nhs: boolean;
|
|
28
|
+
gender: string;
|
|
29
|
+
date_of_birth: string;
|
|
30
|
+
condition_id: string | number;
|
|
31
|
+
condition_name: string;
|
|
32
|
+
branch_corporate_id?: string | number;
|
|
33
|
+
}
|
|
34
|
+
declare function trackStartAssessmentClicked(params: StartAssessmentClickedParams): void;
|
|
35
|
+
interface EligibilityCheckedParams {
|
|
36
|
+
status: 'passed' | 'failed';
|
|
37
|
+
gender: string;
|
|
38
|
+
date_of_birth: string;
|
|
39
|
+
condition_name: string;
|
|
40
|
+
condition_id: string | number;
|
|
41
|
+
branch_corporate_id?: string | number;
|
|
42
|
+
}
|
|
43
|
+
declare function trackEligibilityChecked(params: EligibilityCheckedParams): void;
|
|
44
|
+
interface QuestionnaireFlowStepParams {
|
|
45
|
+
step: string;
|
|
46
|
+
condition_token: string;
|
|
47
|
+
condition_id: string | number;
|
|
48
|
+
condition_name: string;
|
|
49
|
+
user_journey_flow: string;
|
|
50
|
+
branch_corporate_id?: string | number;
|
|
51
|
+
}
|
|
52
|
+
declare function trackQuestionnaireFlowStep(params: QuestionnaireFlowStepParams): void;
|
|
53
|
+
interface ProductTrackingParams {
|
|
54
|
+
product_slug: string;
|
|
55
|
+
product_name: string;
|
|
56
|
+
product_id: string | number;
|
|
57
|
+
core_drug_id?: number;
|
|
58
|
+
branch_corporate_id?: string | number;
|
|
59
|
+
condition_id?: string | number;
|
|
60
|
+
condition_name?: string;
|
|
61
|
+
source?: string;
|
|
62
|
+
category_type?: string;
|
|
63
|
+
}
|
|
64
|
+
declare function trackProductViewed(params: ProductTrackingParams): void;
|
|
65
|
+
interface GetTreatmentClickedParams {
|
|
66
|
+
product_slug: string;
|
|
67
|
+
product_name: string;
|
|
68
|
+
category_type?: string;
|
|
69
|
+
product_id: string | number;
|
|
70
|
+
core_drug_id?: number;
|
|
71
|
+
branch_corporate_id?: string | number;
|
|
72
|
+
condition_id?: string | number;
|
|
73
|
+
condition_name?: string;
|
|
74
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
75
|
+
button_origin?: string;
|
|
76
|
+
}
|
|
77
|
+
declare function trackGetTreatmentClicked(params: GetTreatmentClickedParams): void;
|
|
78
|
+
interface PMStartAssessmentClickedParams {
|
|
79
|
+
branch_corporate_id?: string | number;
|
|
80
|
+
condition_id?: string | number;
|
|
81
|
+
condition_name?: string;
|
|
82
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
83
|
+
}
|
|
84
|
+
declare function trackPMStartAssessmentClicked(params: PMStartAssessmentClickedParams): void;
|
|
85
|
+
interface AuthCompletedParams {
|
|
86
|
+
method: 'signup' | 'signin' | 'guest' | 'already_logged_in';
|
|
87
|
+
branch_corporate_id?: string | number;
|
|
88
|
+
core_drug_id?: number;
|
|
89
|
+
condition_id?: string | number;
|
|
90
|
+
condition_name?: string;
|
|
91
|
+
formulary?: string;
|
|
92
|
+
product_name?: string;
|
|
93
|
+
user_name?: string;
|
|
94
|
+
user_email?: string;
|
|
95
|
+
user_gender?: string;
|
|
96
|
+
user_phone?: string;
|
|
97
|
+
user_dob?: string;
|
|
98
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
99
|
+
}
|
|
100
|
+
declare function trackAuthCompleted(params: AuthCompletedParams): void;
|
|
101
|
+
interface QuestionnairePmParams {
|
|
102
|
+
product_id?: string | number;
|
|
103
|
+
product_slug?: string;
|
|
104
|
+
product_name?: string;
|
|
105
|
+
core_drug_id?: number;
|
|
106
|
+
condition_id?: string | number;
|
|
107
|
+
condition_name?: string;
|
|
108
|
+
branch_corporate_id?: string | number;
|
|
109
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
110
|
+
}
|
|
111
|
+
declare function trackQuestionnairePm(params: QuestionnairePmParams): void;
|
|
112
|
+
interface CartViewedParams {
|
|
113
|
+
product_id?: string | number;
|
|
114
|
+
product_slug?: string;
|
|
115
|
+
product_name?: string;
|
|
116
|
+
branch_corporate_id?: string | number;
|
|
117
|
+
core_drug_id?: number;
|
|
118
|
+
condition_id?: string | number;
|
|
119
|
+
condition_name?: string;
|
|
120
|
+
cart_item_count?: number;
|
|
121
|
+
cart_total_price?: number;
|
|
122
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
123
|
+
/** 'signed_in' when user is authenticated, 'guest' when browsing as a guest */
|
|
124
|
+
cart_auth_status?: 'signed_in' | 'guest';
|
|
125
|
+
}
|
|
126
|
+
declare function trackCartViewed(params: CartViewedParams): void;
|
|
127
|
+
interface CheckoutStartedParams {
|
|
128
|
+
product_id?: string | number;
|
|
129
|
+
product_slug?: string;
|
|
130
|
+
product_name?: string;
|
|
131
|
+
branch_corporate_id?: string | number;
|
|
132
|
+
core_drug_id?: number;
|
|
133
|
+
condition_id?: string | number;
|
|
134
|
+
condition_name?: string;
|
|
135
|
+
cart_item_count?: number;
|
|
136
|
+
cart_total_price?: number;
|
|
137
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
138
|
+
}
|
|
139
|
+
declare function trackCheckoutStarted(params: CheckoutStartedParams): void;
|
|
140
|
+
interface OrderSuccessParams {
|
|
141
|
+
product_id?: string | number;
|
|
142
|
+
product_slug?: string;
|
|
143
|
+
product_name?: string;
|
|
144
|
+
branch_corporate_id?: string | number;
|
|
145
|
+
core_drug_id?: number;
|
|
146
|
+
condition_id?: string | number;
|
|
147
|
+
condition_name?: string;
|
|
148
|
+
order_id?: string | number;
|
|
149
|
+
cart_item_count?: number;
|
|
150
|
+
cart_total_price?: number;
|
|
151
|
+
payment_mode?: string;
|
|
152
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
153
|
+
}
|
|
154
|
+
declare function trackOrderSuccess(params: OrderSuccessParams): void;
|
|
155
|
+
interface CartAuthCompletedParams {
|
|
156
|
+
method: 'signup' | 'signin' | 'guest';
|
|
157
|
+
product_id?: string | number;
|
|
158
|
+
product_slug?: string;
|
|
159
|
+
product_name?: string;
|
|
160
|
+
branch_corporate_id?: string | number;
|
|
161
|
+
core_drug_id?: number;
|
|
162
|
+
condition_id?: string | number;
|
|
163
|
+
condition_name?: string;
|
|
164
|
+
user_name?: string;
|
|
165
|
+
user_email?: string;
|
|
166
|
+
user_gender?: string;
|
|
167
|
+
user_phone?: string;
|
|
168
|
+
user_dob?: string;
|
|
169
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
170
|
+
}
|
|
171
|
+
declare function trackCartAuthCompleted(params: CartAuthCompletedParams): void;
|
|
172
|
+
interface ProductSelectedParams {
|
|
173
|
+
product_id?: string | number;
|
|
174
|
+
product_slug?: string;
|
|
175
|
+
product_name?: string;
|
|
176
|
+
core_drug_id?: number;
|
|
177
|
+
condition_id?: string | number;
|
|
178
|
+
condition_name?: string;
|
|
179
|
+
branch_corporate_id?: string | number;
|
|
180
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
181
|
+
}
|
|
182
|
+
declare function trackProductSelected(params: ProductSelectedParams): void;
|
|
183
|
+
interface ConditionSearchedParams {
|
|
184
|
+
search_term: string;
|
|
185
|
+
results_count: number;
|
|
186
|
+
source: 'hero' | 'nav' | 'mobile_nav' | 'page';
|
|
187
|
+
}
|
|
188
|
+
declare function trackConditionSearched(params: ConditionSearchedParams): void;
|
|
189
|
+
interface ProductSearchedParams {
|
|
190
|
+
search_term: string;
|
|
191
|
+
results_count: number;
|
|
192
|
+
}
|
|
193
|
+
declare function trackProductSearched(params: ProductSearchedParams): void;
|
|
194
|
+
|
|
195
|
+
interface GaScriptProps {
|
|
196
|
+
measurementId?: string | null;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Injects the GA4 gtag.js script globally in Next.js layout.
|
|
200
|
+
*
|
|
201
|
+
* Loaded with `beforeInteractive` priority so `gtag` is always available.
|
|
202
|
+
* Consent is initialized as DENIED by default until user accepts cookies.
|
|
203
|
+
*/
|
|
204
|
+
declare function GaScript({ measurementId }: GaScriptProps): react__default.JSX.Element | null;
|
|
205
|
+
|
|
206
|
+
interface MixpanelInitProps {
|
|
207
|
+
token?: string | null;
|
|
208
|
+
}
|
|
209
|
+
declare function MixpanelInit({ token }?: MixpanelInitProps): null;
|
|
210
|
+
|
|
211
|
+
declare function AnalyticsProvider({ children }: {
|
|
212
|
+
children: react__default.ReactNode;
|
|
213
|
+
}): react__default.JSX.Element;
|
|
214
|
+
|
|
215
|
+
export { AnalyticsProvider, type AuthCompletedParams, type CartAuthCompletedParams, type CartViewedParams, type CheckoutStartedParams, type ConditionSearchedParams, type ConditionTrackingParams, type EligibilityCheckedParams, GaScript, type GaScriptProps, type GetTreatmentClickedParams, MixpanelInit, type MixpanelInitProps, type OrderSuccessParams, type PMStartAssessmentClickedParams, type ProductSearchedParams, type ProductSelectedParams, type ProductTrackingParams, type QuestionnaireFlowStepParams, type QuestionnairePmParams, type StartAssessmentClickedParams, trackAuthCompleted, trackCartAuthCompleted, trackCartViewed, trackCheckoutStarted, trackConditionSearched, trackConditionViewed, trackEligibilityChecked, trackEvent, trackGetTreatmentClicked, trackOrderSuccess, trackPMStartAssessmentClicked, trackPageView, trackProductSearched, trackProductSelected, trackProductViewed, trackQuestionnaireFlowStep, trackQuestionnairePm, trackStartAssessmentClicked };
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import react__default from 'react';
|
|
2
|
+
|
|
3
|
+
declare global {
|
|
4
|
+
interface Window {
|
|
5
|
+
gtag: (...args: unknown[]) => void;
|
|
6
|
+
dataLayer: unknown[];
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Fires an analytics event to GA4 (via gtag) and Mixpanel in parallel.
|
|
11
|
+
* No-ops server-side. GA4 is skipped when gtag is unavailable (e.g. consent denied).
|
|
12
|
+
*/
|
|
13
|
+
declare function trackEvent(eventName: string, params?: Record<string, unknown>): void;
|
|
14
|
+
declare function trackPageView(pagePath: string, pageTitle: string): void;
|
|
15
|
+
interface ConditionTrackingParams {
|
|
16
|
+
condition_slug: string;
|
|
17
|
+
condition_name: string;
|
|
18
|
+
condition_id: string | number;
|
|
19
|
+
branch_corporate_id?: string | number;
|
|
20
|
+
source?: string;
|
|
21
|
+
is_pre_consult: boolean;
|
|
22
|
+
is_private_medication: boolean;
|
|
23
|
+
}
|
|
24
|
+
declare function trackConditionViewed(params: ConditionTrackingParams): void;
|
|
25
|
+
interface StartAssessmentClickedParams {
|
|
26
|
+
eligibility_status: 'passed' | 'failed';
|
|
27
|
+
is_nhs: boolean;
|
|
28
|
+
gender: string;
|
|
29
|
+
date_of_birth: string;
|
|
30
|
+
condition_id: string | number;
|
|
31
|
+
condition_name: string;
|
|
32
|
+
branch_corporate_id?: string | number;
|
|
33
|
+
}
|
|
34
|
+
declare function trackStartAssessmentClicked(params: StartAssessmentClickedParams): void;
|
|
35
|
+
interface EligibilityCheckedParams {
|
|
36
|
+
status: 'passed' | 'failed';
|
|
37
|
+
gender: string;
|
|
38
|
+
date_of_birth: string;
|
|
39
|
+
condition_name: string;
|
|
40
|
+
condition_id: string | number;
|
|
41
|
+
branch_corporate_id?: string | number;
|
|
42
|
+
}
|
|
43
|
+
declare function trackEligibilityChecked(params: EligibilityCheckedParams): void;
|
|
44
|
+
interface QuestionnaireFlowStepParams {
|
|
45
|
+
step: string;
|
|
46
|
+
condition_token: string;
|
|
47
|
+
condition_id: string | number;
|
|
48
|
+
condition_name: string;
|
|
49
|
+
user_journey_flow: string;
|
|
50
|
+
branch_corporate_id?: string | number;
|
|
51
|
+
}
|
|
52
|
+
declare function trackQuestionnaireFlowStep(params: QuestionnaireFlowStepParams): void;
|
|
53
|
+
interface ProductTrackingParams {
|
|
54
|
+
product_slug: string;
|
|
55
|
+
product_name: string;
|
|
56
|
+
product_id: string | number;
|
|
57
|
+
core_drug_id?: number;
|
|
58
|
+
branch_corporate_id?: string | number;
|
|
59
|
+
condition_id?: string | number;
|
|
60
|
+
condition_name?: string;
|
|
61
|
+
source?: string;
|
|
62
|
+
category_type?: string;
|
|
63
|
+
}
|
|
64
|
+
declare function trackProductViewed(params: ProductTrackingParams): void;
|
|
65
|
+
interface GetTreatmentClickedParams {
|
|
66
|
+
product_slug: string;
|
|
67
|
+
product_name: string;
|
|
68
|
+
category_type?: string;
|
|
69
|
+
product_id: string | number;
|
|
70
|
+
core_drug_id?: number;
|
|
71
|
+
branch_corporate_id?: string | number;
|
|
72
|
+
condition_id?: string | number;
|
|
73
|
+
condition_name?: string;
|
|
74
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
75
|
+
button_origin?: string;
|
|
76
|
+
}
|
|
77
|
+
declare function trackGetTreatmentClicked(params: GetTreatmentClickedParams): void;
|
|
78
|
+
interface PMStartAssessmentClickedParams {
|
|
79
|
+
branch_corporate_id?: string | number;
|
|
80
|
+
condition_id?: string | number;
|
|
81
|
+
condition_name?: string;
|
|
82
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
83
|
+
}
|
|
84
|
+
declare function trackPMStartAssessmentClicked(params: PMStartAssessmentClickedParams): void;
|
|
85
|
+
interface AuthCompletedParams {
|
|
86
|
+
method: 'signup' | 'signin' | 'guest' | 'already_logged_in';
|
|
87
|
+
branch_corporate_id?: string | number;
|
|
88
|
+
core_drug_id?: number;
|
|
89
|
+
condition_id?: string | number;
|
|
90
|
+
condition_name?: string;
|
|
91
|
+
formulary?: string;
|
|
92
|
+
product_name?: string;
|
|
93
|
+
user_name?: string;
|
|
94
|
+
user_email?: string;
|
|
95
|
+
user_gender?: string;
|
|
96
|
+
user_phone?: string;
|
|
97
|
+
user_dob?: string;
|
|
98
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
99
|
+
}
|
|
100
|
+
declare function trackAuthCompleted(params: AuthCompletedParams): void;
|
|
101
|
+
interface QuestionnairePmParams {
|
|
102
|
+
product_id?: string | number;
|
|
103
|
+
product_slug?: string;
|
|
104
|
+
product_name?: string;
|
|
105
|
+
core_drug_id?: number;
|
|
106
|
+
condition_id?: string | number;
|
|
107
|
+
condition_name?: string;
|
|
108
|
+
branch_corporate_id?: string | number;
|
|
109
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
110
|
+
}
|
|
111
|
+
declare function trackQuestionnairePm(params: QuestionnairePmParams): void;
|
|
112
|
+
interface CartViewedParams {
|
|
113
|
+
product_id?: string | number;
|
|
114
|
+
product_slug?: string;
|
|
115
|
+
product_name?: string;
|
|
116
|
+
branch_corporate_id?: string | number;
|
|
117
|
+
core_drug_id?: number;
|
|
118
|
+
condition_id?: string | number;
|
|
119
|
+
condition_name?: string;
|
|
120
|
+
cart_item_count?: number;
|
|
121
|
+
cart_total_price?: number;
|
|
122
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
123
|
+
/** 'signed_in' when user is authenticated, 'guest' when browsing as a guest */
|
|
124
|
+
cart_auth_status?: 'signed_in' | 'guest';
|
|
125
|
+
}
|
|
126
|
+
declare function trackCartViewed(params: CartViewedParams): void;
|
|
127
|
+
interface CheckoutStartedParams {
|
|
128
|
+
product_id?: string | number;
|
|
129
|
+
product_slug?: string;
|
|
130
|
+
product_name?: string;
|
|
131
|
+
branch_corporate_id?: string | number;
|
|
132
|
+
core_drug_id?: number;
|
|
133
|
+
condition_id?: string | number;
|
|
134
|
+
condition_name?: string;
|
|
135
|
+
cart_item_count?: number;
|
|
136
|
+
cart_total_price?: number;
|
|
137
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
138
|
+
}
|
|
139
|
+
declare function trackCheckoutStarted(params: CheckoutStartedParams): void;
|
|
140
|
+
interface OrderSuccessParams {
|
|
141
|
+
product_id?: string | number;
|
|
142
|
+
product_slug?: string;
|
|
143
|
+
product_name?: string;
|
|
144
|
+
branch_corporate_id?: string | number;
|
|
145
|
+
core_drug_id?: number;
|
|
146
|
+
condition_id?: string | number;
|
|
147
|
+
condition_name?: string;
|
|
148
|
+
order_id?: string | number;
|
|
149
|
+
cart_item_count?: number;
|
|
150
|
+
cart_total_price?: number;
|
|
151
|
+
payment_mode?: string;
|
|
152
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
153
|
+
}
|
|
154
|
+
declare function trackOrderSuccess(params: OrderSuccessParams): void;
|
|
155
|
+
interface CartAuthCompletedParams {
|
|
156
|
+
method: 'signup' | 'signin' | 'guest';
|
|
157
|
+
product_id?: string | number;
|
|
158
|
+
product_slug?: string;
|
|
159
|
+
product_name?: string;
|
|
160
|
+
branch_corporate_id?: string | number;
|
|
161
|
+
core_drug_id?: number;
|
|
162
|
+
condition_id?: string | number;
|
|
163
|
+
condition_name?: string;
|
|
164
|
+
user_name?: string;
|
|
165
|
+
user_email?: string;
|
|
166
|
+
user_gender?: string;
|
|
167
|
+
user_phone?: string;
|
|
168
|
+
user_dob?: string;
|
|
169
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
170
|
+
}
|
|
171
|
+
declare function trackCartAuthCompleted(params: CartAuthCompletedParams): void;
|
|
172
|
+
interface ProductSelectedParams {
|
|
173
|
+
product_id?: string | number;
|
|
174
|
+
product_slug?: string;
|
|
175
|
+
product_name?: string;
|
|
176
|
+
core_drug_id?: number;
|
|
177
|
+
condition_id?: string | number;
|
|
178
|
+
condition_name?: string;
|
|
179
|
+
branch_corporate_id?: string | number;
|
|
180
|
+
pm_flow_source?: 'product_detail' | 'condition_detail';
|
|
181
|
+
}
|
|
182
|
+
declare function trackProductSelected(params: ProductSelectedParams): void;
|
|
183
|
+
interface ConditionSearchedParams {
|
|
184
|
+
search_term: string;
|
|
185
|
+
results_count: number;
|
|
186
|
+
source: 'hero' | 'nav' | 'mobile_nav' | 'page';
|
|
187
|
+
}
|
|
188
|
+
declare function trackConditionSearched(params: ConditionSearchedParams): void;
|
|
189
|
+
interface ProductSearchedParams {
|
|
190
|
+
search_term: string;
|
|
191
|
+
results_count: number;
|
|
192
|
+
}
|
|
193
|
+
declare function trackProductSearched(params: ProductSearchedParams): void;
|
|
194
|
+
|
|
195
|
+
interface GaScriptProps {
|
|
196
|
+
measurementId?: string | null;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Injects the GA4 gtag.js script globally in Next.js layout.
|
|
200
|
+
*
|
|
201
|
+
* Loaded with `beforeInteractive` priority so `gtag` is always available.
|
|
202
|
+
* Consent is initialized as DENIED by default until user accepts cookies.
|
|
203
|
+
*/
|
|
204
|
+
declare function GaScript({ measurementId }: GaScriptProps): react__default.JSX.Element | null;
|
|
205
|
+
|
|
206
|
+
interface MixpanelInitProps {
|
|
207
|
+
token?: string | null;
|
|
208
|
+
}
|
|
209
|
+
declare function MixpanelInit({ token }?: MixpanelInitProps): null;
|
|
210
|
+
|
|
211
|
+
declare function AnalyticsProvider({ children }: {
|
|
212
|
+
children: react__default.ReactNode;
|
|
213
|
+
}): react__default.JSX.Element;
|
|
214
|
+
|
|
215
|
+
export { AnalyticsProvider, type AuthCompletedParams, type CartAuthCompletedParams, type CartViewedParams, type CheckoutStartedParams, type ConditionSearchedParams, type ConditionTrackingParams, type EligibilityCheckedParams, GaScript, type GaScriptProps, type GetTreatmentClickedParams, MixpanelInit, type MixpanelInitProps, type OrderSuccessParams, type PMStartAssessmentClickedParams, type ProductSearchedParams, type ProductSelectedParams, type ProductTrackingParams, type QuestionnaireFlowStepParams, type QuestionnairePmParams, type StartAssessmentClickedParams, trackAuthCompleted, trackCartAuthCompleted, trackCartViewed, trackCheckoutStarted, trackConditionSearched, trackConditionViewed, trackEligibilityChecked, trackEvent, trackGetTreatmentClicked, trackOrderSuccess, trackPMStartAssessmentClicked, trackPageView, trackProductSearched, trackProductSelected, trackProductViewed, trackQuestionnaireFlowStep, trackQuestionnairePm, trackStartAssessmentClicked };
|