@digia-engage/core 2.3.2 → 2.4.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.
Files changed (62) hide show
  1. package/DigiaEngageReactNative.podspec +1 -1
  2. package/android/.project +28 -0
  3. package/android/build.gradle +1 -1
  4. package/android/local.properties +1 -0
  5. package/android/src/main/java/com/digia/engage/rn/DigiaModule.kt +64 -6
  6. package/ios/DigiaModule.swift +70 -8
  7. package/ios/RNEventBridgePlugin.swift +2 -0
  8. package/lib/commonjs/Digia.js +139 -100
  9. package/lib/commonjs/Digia.js.map +1 -1
  10. package/lib/commonjs/DigiaAnchorView.js +11 -1
  11. package/lib/commonjs/DigiaAnchorView.js.map +1 -1
  12. package/lib/commonjs/DigiaProvider.js +63 -2
  13. package/lib/commonjs/DigiaProvider.js.map +1 -1
  14. package/lib/commonjs/NativeDigiaEngage.js +3 -0
  15. package/lib/commonjs/NativeDigiaEngage.js.map +1 -1
  16. package/lib/commonjs/digiaAnchorRegistry.js +3 -1
  17. package/lib/commonjs/digiaAnchorRegistry.js.map +1 -1
  18. package/lib/commonjs/frequencyStore.js +3 -3
  19. package/lib/commonjs/frequencyStore.js.map +1 -1
  20. package/lib/commonjs/index.js +0 -7
  21. package/lib/commonjs/index.js.map +1 -1
  22. package/lib/module/Digia.js +139 -100
  23. package/lib/module/Digia.js.map +1 -1
  24. package/lib/module/DigiaAnchorView.js +11 -1
  25. package/lib/module/DigiaAnchorView.js.map +1 -1
  26. package/lib/module/DigiaProvider.js +65 -3
  27. package/lib/module/DigiaProvider.js.map +1 -1
  28. package/lib/module/NativeDigiaEngage.js +3 -0
  29. package/lib/module/NativeDigiaEngage.js.map +1 -1
  30. package/lib/module/digiaAnchorRegistry.js +3 -1
  31. package/lib/module/digiaAnchorRegistry.js.map +1 -1
  32. package/lib/module/frequencyStore.js +3 -3
  33. package/lib/module/frequencyStore.js.map +1 -1
  34. package/lib/module/index.js +4 -4
  35. package/lib/module/index.js.map +1 -1
  36. package/lib/typescript/Digia.d.ts +17 -8
  37. package/lib/typescript/Digia.d.ts.map +1 -1
  38. package/lib/typescript/DigiaAnchorView.d.ts.map +1 -1
  39. package/lib/typescript/DigiaProvider.d.ts +3 -1
  40. package/lib/typescript/DigiaProvider.d.ts.map +1 -1
  41. package/lib/typescript/NativeDigiaEngage.d.ts +9 -0
  42. package/lib/typescript/NativeDigiaEngage.d.ts.map +1 -1
  43. package/lib/typescript/digiaAnchorRegistry.d.ts +1 -0
  44. package/lib/typescript/digiaAnchorRegistry.d.ts.map +1 -1
  45. package/lib/typescript/frequencyStore.d.ts +1 -1
  46. package/lib/typescript/frequencyStore.d.ts.map +1 -1
  47. package/lib/typescript/index.d.ts +5 -5
  48. package/lib/typescript/index.d.ts.map +1 -1
  49. package/lib/typescript/templateTypes.d.ts +24 -1
  50. package/lib/typescript/templateTypes.d.ts.map +1 -1
  51. package/lib/typescript/types.d.ts +17 -13
  52. package/lib/typescript/types.d.ts.map +1 -1
  53. package/package.json +8 -9
  54. package/src/Digia.ts +142 -114
  55. package/src/DigiaAnchorView.tsx +6 -1
  56. package/src/DigiaProvider.tsx +76 -2
  57. package/src/NativeDigiaEngage.ts +20 -0
  58. package/src/digiaAnchorRegistry.ts +3 -1
  59. package/src/frequencyStore.ts +4 -4
  60. package/src/index.ts +5 -5
  61. package/src/templateTypes.ts +31 -1
  62. package/src/types.ts +17 -13
@@ -1,15 +1,19 @@
1
1
  /**
2
- * Payload delivered to the Digia rendering engine for a CEP campaign.
2
+ * The translation contract between a CEP plugin and Digia's rendering engine.
3
3
  *
4
- * Mirrors InAppPayload on Android / Flutter.
4
+ * Plugin authors map their CEP's native callback into this struct.
5
+ * Mirrors CEPTriggerPayload on Android / Flutter — Digia core never imports
6
+ * CleverTap, MoEngage, or WebEngage types directly.
5
7
  */
6
- export interface InAppPayload {
7
- /** Unique campaign ID from the CEP platform. */
8
- id: string;
9
- /** Marketer-authored content map (JSON-serialisable). */
10
- content: Record<string, unknown>;
11
- /** CEP-platform metadata, e.g. { campaignId, campaignName }. */
12
- cepContext: Record<string, unknown>;
8
+ export interface CEPTriggerPayload {
9
+ /** The CEP's own identifier for this campaign instance. Opaque to Digia — passed through for analytics correlation. */
10
+ cepCampaignId: string;
11
+ /** Additional metadata the CEP passes through (UTM params, user segment, CEP-specific tracking fields). Forwarded as-is in ExperienceEvents. */
12
+ cepMetadata: Record<string, unknown>;
13
+ /** The coupling key linking this CEP campaign to a Digia campaign. Used to look up the matching campaign in the store. */
14
+ campaignKey: string;
15
+ /** Optional runtime variables to interpolate into the campaign config. Keys must match variable placeholders in the Digia dashboard. */
16
+ variables?: Record<string, string>;
13
17
  }
14
18
  export type CampaignType = 'nudge' | 'guide' | 'inline' | 'survey';
15
19
  /** The experience became visible to the user. */
@@ -98,7 +102,7 @@ export type GuideLifecycleEvent = {
98
102
  */
99
103
  export interface DigiaDelegate {
100
104
  /** Deliver a campaign payload into the Digia rendering engine. */
101
- onCampaignTriggered(payload: InAppPayload): void | Promise<void>;
105
+ onCampaignTriggered(payload: CEPTriggerPayload): void | Promise<void>;
102
106
  /** Invalidate / dismiss a campaign by its ID. */
103
107
  onCampaignInvalidated(campaignId: string): void;
104
108
  }
@@ -117,7 +121,7 @@ export interface DigiaPlugin {
117
121
  * (impressed / clicked / dismissed). Plugins use this to report
118
122
  * analytics back to their CEP platform.
119
123
  */
120
- notifyEvent(event: DigiaExperienceEvent, payload: InAppPayload): void;
124
+ notifyEvent(event: DigiaExperienceEvent, payload: CEPTriggerPayload): void;
121
125
  /**
122
126
  * Called by the Digia SDK to record a named analytics event with properties.
123
127
  * Implement this to forward Digia lifecycle events (e.g. "Digia Experience Viewed")
@@ -193,8 +197,8 @@ export interface FrequencyEvalResult {
193
197
  * Configuration for initialising the Digia Engage SDK.
194
198
  */
195
199
  export interface DigiaConfig {
196
- /** The Engage project ID — sent as x-digia-project-id on all SDK requests. */
197
- projectId: string;
200
+ /** The Engage API key — sent as x-digia-project-id on all SDK requests. */
201
+ apiKey: string;
198
202
  /**
199
203
  * Base URL for the Digia API.
200
204
  * Defaults to the production API root, or the Engage sandbox root when
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@digia-engage/core",
3
- "version": "2.3.2",
3
+ "version": "2.4.0",
4
4
  "description": "React Native bridge for Digia Engage – renders native Android Compose UI inside React Native apps",
5
5
  "main": "lib/commonjs/index",
6
6
  "module": "lib/module/index",
@@ -45,18 +45,17 @@
45
45
  "author": "Digia Technology Private Limited",
46
46
  "license": "BUSL-1.1",
47
47
  "dependencies": {
48
+ "@floating-ui/core": "^1.0.0",
48
49
  "@react-native-async-storage/async-storage": "^2.1.2",
49
- "react-native-uuid": "^2.0.3",
50
- "@edwardloopez/react-native-coachmark": "^0.5.3",
51
- "@floating-ui/core": "^1.0.0"
50
+ "react-native-svg": "^15.15.5",
51
+ "react-native-uuid": "^2.0.3"
52
52
  },
53
53
  "devDependencies": {
54
- "@react-native/eslint-config": "^0.73.0",
55
- "@types/react": "^18.2.0",
56
- "@types/react-native": "^0.73.0",
54
+ "@react-native/eslint-config": "^0.83.0",
55
+ "@types/react": "^19.0.0",
57
56
  "eslint": "^8.51.0",
58
- "react": "18.2.0",
59
- "react-native": "0.73.0",
57
+ "react": "19.2.0",
58
+ "react-native": "0.83.0",
60
59
  "react-native-builder-bob": "^0.23.0",
61
60
  "typescript": "^5.2.0"
62
61
  },
package/src/Digia.ts CHANGED
@@ -7,7 +7,7 @@
7
7
  * import { Digia } from '@digia/engage-react-native';
8
8
  *
9
9
  * // In your App entry point (e.g. App.tsx):
10
- * await Digia.initialize({ projectId: 'YOUR_PROJECT_ID' });
10
+ * await Digia.initialize({ apiKey: 'YOUR_API_KEY' });
11
11
  *
12
12
  * // Whenever your navigation screen changes:
13
13
  * Digia.setCurrentScreen('Home');
@@ -19,6 +19,7 @@ import { DeviceEventEmitter } from 'react-native';
19
19
  import { nativeDigiaModule } from './NativeDigiaEngage';
20
20
  import { digiaHealthReporter, HealthEventType } from './DigiaHealthReporter';
21
21
  import { digiaGuideController } from './DigiaGuideController';
22
+ import { digiaAnchorRegistry } from './digiaAnchorRegistry';
22
23
  import { parseVariableMap } from './interpolate';
23
24
  import { digiaActionHandler } from './actionHandler';
24
25
  import uuid from 'react-native-uuid';
@@ -26,6 +27,7 @@ import { frequencyStore } from './frequencyStore';
26
27
  import { evaluate, hasPolicy, isSessionPolicy } from './frequencyEvaluator';
27
28
  import type {
28
29
  ActionContext,
30
+ CEPTriggerPayload,
29
31
  CampaignType,
30
32
  DigiaConfig,
31
33
  DigiaDelegate,
@@ -34,7 +36,6 @@ import type {
34
36
  FrequencyPolicy,
35
37
  FrequencyState,
36
38
  GuideLifecycleEvent,
37
- InAppPayload,
38
39
  } from './types';
39
40
  import type { TemplateConfig } from './templateTypes';
40
41
 
@@ -56,11 +57,11 @@ class DigiaClass implements DigiaDelegate {
56
57
  // Tracks whether the native bridge plugin (RNEventBridgePlugin) has been
57
58
  // wired to the native SDK. Done once on the first Digia.register() call.
58
59
  private _nativeBridgeWired = false;
59
- // Cache of triggered payloads keyed by campaign ID, used to reconstruct
60
- // the full InAppPayload when overlay lifecycle events arrive from native.
61
- private readonly _activePayloads = new Map<string, InAppPayload>();
60
+ // Cache of triggered payloads keyed by cepCampaignId, used to reconstruct
61
+ // the full CEPTriggerPayload when overlay lifecycle events arrive from native.
62
+ private readonly _activePayloads = new Map<string, CEPTriggerPayload>();
62
63
  private _engageSubscription: { remove(): void } | null = null;
63
- private _projectId = '';
64
+ private _apiKey = '';
64
65
  private _deviceId = '';
65
66
  private _apiBaseUrl = '';
66
67
  private _logLevel: DigiaConfig['logLevel'] = 'error';
@@ -78,11 +79,12 @@ class DigiaClass implements DigiaDelegate {
78
79
  async initialize(config: DigiaConfig): Promise<void> {
79
80
  const environment = config.environment ?? 'production';
80
81
  const logLevel = config.logLevel ?? 'error';
81
- this._projectId = config.projectId;
82
+ this._apiKey = config.apiKey;
82
83
  this._apiBaseUrl = this._resolveApiBaseUrl(config);
83
84
  this._logLevel = logLevel;
84
85
  this._fontFamily = config.fontFamily?.trim() || undefined;
85
- digiaHealthReporter.init(config.projectId, this._apiBaseUrl);
86
+ this._log(`Digia SDK initializing | apiKey=${config.apiKey.slice(0, 8)}… env=${environment}`);
87
+ digiaHealthReporter.init(config.apiKey, this._apiBaseUrl);
86
88
 
87
89
  digiaActionHandler.configure({
88
90
  onAction: config.onAction,
@@ -93,16 +95,16 @@ class DigiaClass implements DigiaDelegate {
93
95
  });
94
96
 
95
97
  try {
96
- await nativeDigiaModule.initialize(config.projectId, environment, logLevel, config.baseUrl, config.fontFamily);
98
+ await nativeDigiaModule.initialize(config.apiKey, environment, logLevel, config.baseUrl, config.fontFamily);
97
99
  } catch (e) {
98
- // Health-event reporting is currently disabled.
99
- // digiaHealthReporter.report(HealthEventType.fetch_failed, { error_code: 0, platform: 'react_native' });
100
+ this._error(`Digia SDK native init failed: ${e instanceof Error ? e.message : String(e)}`);
100
101
  throw e;
101
102
  }
102
103
 
103
104
  this._deviceId = await this._loadOrCreateDeviceId();
104
- await frequencyStore.checkProjectId(config.projectId);
105
+ await frequencyStore.checkApiKey(config.apiKey);
105
106
  await this._refreshCampaignStore();
107
+ this._log(`Digia SDK ready | campaigns=${this._campaignsByKey.size}`);
106
108
  }
107
109
 
108
110
  /**
@@ -116,13 +118,16 @@ class DigiaClass implements DigiaDelegate {
116
118
  * ```ts
117
119
  * import { DigiaMoEngagePlugin } from '@digia/moengage-plugin';
118
120
  *
119
- * await Digia.initialize({ projectId: 'YOUR_PROJECT_ID' });
121
+ * await Digia.initialize({ apiKey: 'YOUR_API_KEY' });
120
122
  * Digia.register(new DigiaMoEngagePlugin({ moEngage: MoEngage }));
121
123
  * ```
122
124
  */
123
125
  register(plugin: DigiaPlugin): void {
124
126
  if (this._plugins.has(plugin.identifier)) {
127
+ this._log(`Plugin replaced: ${plugin.identifier}`);
125
128
  this._plugins.get(plugin.identifier)!.teardown();
129
+ } else {
130
+ this._log(`Plugin registered: ${plugin.identifier}`);
126
131
  }
127
132
  // Wire the native bridge plugin once, before the first plugin's setup()
128
133
  // so the delegate is ready when JS campaigns start flowing.
@@ -154,6 +159,7 @@ class DigiaClass implements DigiaDelegate {
154
159
  * All registered plugins will have forwardScreen() called automatically.
155
160
  */
156
161
  setCurrentScreen(name: string): void {
162
+ this._log(`Screen: ${name}`);
157
163
  this._currentScreen = name;
158
164
  nativeDigiaModule.setCurrentScreen(name);
159
165
  this._plugins.forEach((plugin) => plugin.forwardScreen(name));
@@ -169,6 +175,22 @@ class DigiaClass implements DigiaDelegate {
169
175
  this._registeredAnchorKeys.delete(anchorKey);
170
176
  }
171
177
 
178
+ /**
179
+ * Associate a known user ID with subsequent analytics events.
180
+ * Call after login; rotates the analytics session automatically.
181
+ */
182
+ setUserId(userId: string): void {
183
+ nativeDigiaModule.setUserId(userId);
184
+ }
185
+
186
+ /**
187
+ * Clear the user ID (e.g. on logout).
188
+ * Subsequent events are attributed to the anonymous ID and a new session.
189
+ */
190
+ clearUserId(): void {
191
+ nativeDigiaModule.clearUserId();
192
+ }
193
+
172
194
  /**
173
195
  * Global font family configured via {@link initialize}, or `undefined` when
174
196
  * none was set. Used by the JS-rendered guide overlays (tooltip/spotlight)
@@ -183,86 +205,101 @@ class DigiaClass implements DigiaDelegate {
183
205
  // Mirrors DigiaCEPDelegate on Android.
184
206
  // Forwards to the native DigiaCEPDelegate via the bridge.
185
207
 
186
- async onCampaignTriggered(payload: InAppPayload): Promise<void> {
208
+ async onCampaignTriggered(payload: CEPTriggerPayload): Promise<void> {
187
209
  if (!this._nativeBridgeWired) {
188
- digiaHealthReporter.report(HealthEventType.plugin_not_registered, { campaign_key: payload.id });
210
+ digiaHealthReporter.report(HealthEventType.plugin_not_registered, { campaign_key: payload.campaignKey });
189
211
  }
190
212
 
191
- const campaignKey = this._extractCampaignKey(payload);
192
- this._log(`onCampaignTriggered payloadId=${payload.id} extractedKey=${campaignKey} knownKeys=[${[...this._campaignsByKey.keys()].join(', ')}]`);
213
+ const { cepCampaignId, campaignKey, variables, cepMetadata } = payload;
214
+ this._log(`onCampaignTriggered cepCampaignId=${cepCampaignId} campaignKey=${campaignKey} knownKeys=[${[...this._campaignsByKey.keys()].join(', ')}]`);
193
215
 
194
- if (campaignKey) {
195
- const campaign = this._campaignsByKey.get(campaignKey);
196
-
197
- if (campaign && hasPolicy(campaign.frequency)) {
198
- const policy = campaign.frequency!;
199
- const isSession = isSessionPolicy(policy);
200
- const state = await this._getFrequencyState(campaignKey, isSession);
201
- const result = evaluate(policy, state, Date.now());
202
- if (!result.allow) {
203
- this._log(`frequency_capped campaign_key=${campaignKey} reason=${result.reason}`);
204
- return;
205
- }
206
- }
216
+ const campaign = this._campaignsByKey.get(campaignKey);
207
217
 
208
- if (campaign?.campaign_type === 'inline' || campaign?.campaign_type === 'survey') {
209
- this._log(`${campaign.campaign_type} campaign triggered campaign_key=${campaignKey}, forwarding to native`);
210
- this._activePayloads.set(payload.id, payload);
211
- if (campaign.campaign_type === 'inline') {
212
- this._emitSlotWidth(campaign);
213
- }
214
- nativeDigiaModule.triggerCampaign(payload.id, payload.content, payload.cepContext);
218
+ if (campaign && hasPolicy(campaign.frequency)) {
219
+ const policy = campaign.frequency!;
220
+ const isSession = isSessionPolicy(policy);
221
+ const state = await this._getFrequencyState(campaignKey, isSession);
222
+ const result = evaluate(policy, state, Date.now());
223
+ if (!result.allow) {
224
+ this._log(`frequency_capped campaign_key=${campaignKey} reason=${result.reason}`);
215
225
  return;
216
226
  }
227
+ }
217
228
 
218
- if (campaign?.campaign_type === 'guide') {
219
- const config = this._parseTemplateConfig(campaign);
220
- if (
221
- !config ||
222
- (config.templateType !== 'tooltip' && config.templateType !== 'spotlight') ||
223
- config.steps.length === 0
224
- ) {
225
- digiaHealthReporter.report(HealthEventType.anchor_not_on_screen, {
226
- campaign_key: campaignKey,
227
- reason: 'guide_campaign_has_no_steps',
228
- });
229
- return;
230
- }
229
+ // Synthesise the content map expected by the native bridge.
230
+ const bridgeContent: Record<string, unknown> = { digia_campaign_key: campaignKey };
231
+ if (variables) bridgeContent.variables = variables;
231
232
 
232
- this._activePayloads.set(payload.id, payload);
233
- const digiaId = campaign._id ?? campaign.id ?? campaignKey;
234
- const mounted = digiaGuideController.start({
235
- payloadId: payload.id,
236
- campaignKey,
237
- campaignId: digiaId,
238
- variables: this._extractVariables(payload),
239
- config,
240
- onExperienceEvent: (event) => this._onGuideLifecycleEvent(event, payload.id, campaignKey, digiaId),
241
- });
233
+ if (campaign?.campaign_type === 'inline' || campaign?.campaign_type === 'survey') {
234
+ this._log(`${campaign.campaign_type} campaign triggered campaign_key=${campaignKey}, forwarding to native`);
235
+ this._activePayloads.set(cepCampaignId, payload);
236
+ if (campaign.campaign_type === 'inline') {
237
+ this._emitSlotWidth(campaign);
238
+ }
239
+ nativeDigiaModule.triggerCampaign(cepCampaignId, bridgeContent, cepMetadata);
240
+ return;
241
+ }
242
242
 
243
- this._log(`guide trigger campaign_key=${campaignKey} mounted=${mounted}`);
244
- if (!mounted) {
245
- digiaHealthReporter.report(HealthEventType.host_not_mounted, {
246
- campaign_key: campaignKey,
247
- payload_id: payload.id,
248
- });
249
- }
243
+ if (campaign?.campaign_type === 'guide') {
244
+ const config = this._parseTemplateConfig(campaign);
245
+ if (
246
+ !config ||
247
+ (config.templateType !== 'tooltip' && config.templateType !== 'spotlight') ||
248
+ config.steps.length === 0
249
+ ) {
250
+ digiaHealthReporter.report(HealthEventType.anchor_not_on_screen, {
251
+ campaign_key: campaignKey,
252
+ reason: 'guide_campaign_has_no_steps',
253
+ });
250
254
  return;
251
255
  }
252
256
 
253
- if (!campaign) {
254
- this._log(`campaign_key_mismatch: no campaign found for key="${campaignKey}"`);
255
- digiaHealthReporter.report(HealthEventType.campaign_key_mismatch, {
257
+ const firstAnchorKey = config.steps[0].anchorKey;
258
+ if (!digiaAnchorRegistry.isRegistered(firstAnchorKey)) {
259
+ // eslint-disable-next-line no-console
260
+ console.warn(`[Digia] campaign dropped — anchor_key "${firstAnchorKey}" is not registered on this screen (campaign_key=${campaignKey})`);
261
+ digiaHealthReporter.report(HealthEventType.anchor_not_on_screen, {
256
262
  campaign_key: campaignKey,
257
- payload_id: payload.id,
258
- available_campaign_keys: [...this._campaignsByKey.keys()],
263
+ reason: 'anchor_key_not_registered',
264
+ anchor_key: firstAnchorKey,
259
265
  });
260
266
  return;
261
267
  }
268
+
269
+ this._activePayloads.set(cepCampaignId, payload);
270
+ const digiaId = campaign._id ?? campaign.id ?? campaignKey;
271
+ const mounted = digiaGuideController.start({
272
+ payloadId: cepCampaignId,
273
+ campaignKey,
274
+ campaignId: digiaId,
275
+ variables,
276
+ config,
277
+ onExperienceEvent: (event) => this._onGuideLifecycleEvent(event, cepCampaignId, campaignKey, digiaId),
278
+ });
279
+
280
+ this._log(`guide trigger campaign_key=${campaignKey} mounted=${mounted}`);
281
+ if (!mounted) {
282
+ this._log(`event controller failed to mount guide campaign_key=${campaignKey}`);
283
+ digiaHealthReporter.report(HealthEventType.host_not_mounted, {
284
+ campaign_key: campaignKey,
285
+ payload_id: cepCampaignId,
286
+ });
287
+ }
288
+ return;
262
289
  }
263
290
 
264
- this._activePayloads.set(payload.id, payload);
265
- nativeDigiaModule.triggerCampaign(payload.id, payload.content, payload.cepContext);
291
+ if (!campaign) {
292
+ this._log(`campaign_key_mismatch: no campaign found for key="${campaignKey}"`);
293
+ digiaHealthReporter.report(HealthEventType.campaign_key_mismatch, {
294
+ campaign_key: campaignKey,
295
+ payload_id: cepCampaignId,
296
+ available_campaign_keys: [...this._campaignsByKey.keys()],
297
+ });
298
+ return;
299
+ }
300
+
301
+ this._activePayloads.set(cepCampaignId, payload);
302
+ nativeDigiaModule.triggerCampaign(cepCampaignId, bridgeContent, cepMetadata);
266
303
  }
267
304
 
268
305
  onCampaignInvalidated(campaignId: string): void {
@@ -292,7 +329,7 @@ class DigiaClass implements DigiaDelegate {
292
329
 
293
330
  private _fireCustomEvent(
294
331
  eventName: string,
295
- properties?: Record<string, unknown>,
332
+ _properties?: Record<string, unknown>,
296
333
  context?: ActionContext,
297
334
  ): void {
298
335
  const payload = context ? this._activePayloads.get(context.campaign_id) : null;
@@ -306,24 +343,25 @@ class DigiaClass implements DigiaDelegate {
306
343
  private _forwardExperienceEvent(
307
344
  data: { campaignId: string; type: string; elementId?: string },
308
345
  ): void {
346
+ console.log(`[Digia] received overlay event from native: campaignId=${data.campaignId} type=${data.type} elementId=${data.elementId}`);
309
347
  const payload = this._activePayloads.get(data.campaignId);
310
348
  if (!payload) return;
311
349
 
312
- const campaignKey = this._extractCampaignKey(payload);
350
+ const { campaignKey } = payload;
313
351
 
314
352
  let event: DigiaExperienceEvent;
315
353
  switch (data.type) {
316
354
  case 'impressed':
317
355
  event = { type: 'impressed' };
318
- if (campaignKey) void this._bumpFrequencyImpression(campaignKey);
356
+ void this._bumpFrequencyImpression(campaignKey);
319
357
  break;
320
358
  case 'clicked':
321
359
  event = { type: 'clicked', elementId: data.elementId };
322
- if (campaignKey) void this._applyStopOn(campaignKey, 'click');
360
+ void this._applyStopOn(campaignKey, 'click');
323
361
  break;
324
362
  case 'dismissed':
325
363
  event = { type: 'dismissed' };
326
- if (campaignKey) void this._applyStopOn(campaignKey, 'dismiss');
364
+ void this._applyStopOn(campaignKey, 'dismiss');
327
365
  this._activePayloads.delete(data.campaignId);
328
366
  break;
329
367
  default:
@@ -339,10 +377,21 @@ class DigiaClass implements DigiaDelegate {
339
377
  campaignKey: string,
340
378
  campaignId: string,
341
379
  ): void {
380
+ console.log(`[Digia] guide lifecycle event: type=${event.type} step=${event.stepIndex + 1}/${event.stepTotal} anchorKey=${event.anchorKey} displayStyle=${event.displayStyle} campaignKey=${campaignKey}`);
342
381
  const eventName = this._guideEventName(event.type);
343
382
  const properties = this._buildGuideProperties(event, campaignId, campaignKey);
344
383
  this._plugins.forEach((p) => p.track?.(eventName, properties));
345
384
 
385
+ // Forward main experience events to native analytics.
386
+ // step_* and completed events are guide-specific and have no native equivalent.
387
+ if (event.type === 'viewed') {
388
+ nativeDigiaModule.trackEvent('impressed', campaignId, campaignKey, 'guide', null);
389
+ } else if (event.type === 'clicked') {
390
+ nativeDigiaModule.trackEvent('clicked', campaignId, campaignKey, 'guide', event.elementId ?? null);
391
+ } else if (event.type === 'dismissed') {
392
+ nativeDigiaModule.trackEvent('dismissed', campaignId, campaignKey, 'guide', null);
393
+ }
394
+
346
395
  if (event.type === 'viewed') {
347
396
  void this._bumpFrequencyImpression(campaignKey);
348
397
  }
@@ -442,7 +491,7 @@ class DigiaClass implements DigiaDelegate {
442
491
  this._log(`loaded ${campaigns.length} campaign(s): [${[...this._campaignsByKey.keys()].join(', ')}]`);
443
492
  } catch (e) {
444
493
  const reason = e instanceof Error ? e.message : String(e);
445
- this._log(`getCampaigns FAILED: ${reason}`);
494
+ this._error(`Campaign fetch failed: ${reason} — check your apiKey and network connectivity`);
446
495
  digiaHealthReporter.report(HealthEventType.fetch_failed, {
447
496
  error_code: 0,
448
497
  platform: 'react_native',
@@ -456,7 +505,7 @@ class DigiaClass implements DigiaDelegate {
456
505
  method: 'POST',
457
506
  headers: {
458
507
  'Content-Type': 'application/json',
459
- 'x-digia-project-id': this._projectId,
508
+ 'x-digia-project-id': this._apiKey,
460
509
  'x-digia-device-id': this._deviceId,
461
510
  },
462
511
  body: JSON.stringify(body),
@@ -506,39 +555,6 @@ class DigiaClass implements DigiaDelegate {
506
555
  }
507
556
  }
508
557
 
509
- private _extractCampaignKey(payload: InAppPayload): string | null {
510
- const fromContent = this._extractString(payload.content, 'digia_campaign_key', 'digiaKey', 'campaign_key', 'campaignKey');
511
- if (fromContent) return fromContent;
512
-
513
- const args = payload.content.args;
514
- if (args && typeof args === 'object' && !Array.isArray(args)) {
515
- const fromArgs = this._extractString(args as Record<string, unknown>, 'digia_campaign_key', 'digiaKey', 'campaign_key', 'campaignKey');
516
- if (fromArgs) return fromArgs;
517
- }
518
-
519
- if (this._campaignsByKey.has(payload.id)) return payload.id;
520
- return null;
521
- }
522
-
523
- private _extractVariables(payload: InAppPayload): Record<string, string> | undefined {
524
- const fromContent = parseVariableMap(payload.content.variables);
525
- if (fromContent) return fromContent;
526
-
527
- const args = payload.content.args;
528
- if (args && typeof args === 'object' && !Array.isArray(args)) {
529
- return parseVariableMap((args as Record<string, unknown>).variables);
530
- }
531
- return undefined;
532
- }
533
-
534
- private _extractString(data: Record<string, unknown>, ...keys: string[]): string | null {
535
- for (const key of keys) {
536
- const value = data[key];
537
- if (typeof value === 'string' && value.trim()) return value.trim();
538
- }
539
- return null;
540
- }
541
-
542
558
  private _parseTemplateConfig(campaign: SdkCampaign): TemplateConfig | null {
543
559
  const c = campaign as unknown as Record<string, unknown>;
544
560
  const raw = c.templateConfig as Record<string, unknown> | undefined;
@@ -622,6 +638,18 @@ class DigiaClass implements DigiaDelegate {
622
638
  console.log(`[Digia] ${message}`);
623
639
  }
624
640
 
641
+ private _warn(message: string): void {
642
+ if (this._logLevel === 'none') return;
643
+ // eslint-disable-next-line no-console
644
+ console.warn(`[Digia] ${message}`);
645
+ }
646
+
647
+ private _error(message: string): void {
648
+ if (this._logLevel === 'none') return;
649
+ // eslint-disable-next-line no-console
650
+ console.error(`[Digia] ${message}`);
651
+ }
652
+
625
653
  }
626
654
 
627
655
  export const Digia = new DigiaClass();
@@ -47,7 +47,12 @@ export const DigiaAnchorView = forwardRef<DigiaAnchorViewRef, Props>(
47
47
  const measure = useCallback(() => {
48
48
  if (!canMeasure.current) return;
49
49
  viewRef.current?.measure((_x, _y, width, height, pageX, pageY) => {
50
- if (width === 0 && height === 0) return;
50
+ if (width === 0 && height === 0) {
51
+ // Publish 0×0 so overlay subscribers can detect a collapsed/hidden
52
+ // anchor and cancel the campaign rather than hanging indefinitely.
53
+ digiaAnchorRegistry.setLayout(anchorKey, { pageX, pageY, width: 0, height: 0 });
54
+ return;
55
+ }
51
56
  nativeDigiaModule.registerAnchor(anchorKey, Math.round(pageX), Math.round(pageY), Math.round(width), Math.round(height));
52
57
  digiaAnchorRegistry.setLayout(anchorKey, { pageX, pageY, width, height });
53
58
  });