Skip to content

feat(types): complete PurchaselyEventProperties with missing public event fields#242

Open
kherembourg wants to merge 1 commit into
mainfrom
feat/types-event-properties-completion
Open

feat(types): complete PurchaselyEventProperties with missing public event fields#242
kherembourg wants to merge 1 commit into
mainfrom
feat/types-event-properties-completion

Conversation

@kherembourg
Copy link
Copy Markdown
Contributor

@kherembourg kherembourg commented May 22, 2026

Summary

Following #240 (placement_id), the SDK emits several other event-context properties at runtime that are still missing from PurchaselyEventProperties, forcing consumers to cast event.properties to access them.

This PR adds all non-internal fields currently serialized by the native SDKs.

Verification

Cross-checked against the native models:

  • AndroidPLYEventProperties.kt: each @SerialName(\"…\") field reaches the bridge via event.properties.toMap() (kotlinx.serializationJSONObject.toMap()).
  • iOSPLYEventProperty.swift: the name getter returns the snake_case key emitted on the bridge.

Each added field exists in at least one of the two native models and is not marked internal.

Fields added

Presentation context: is_fallback_presentation, presentation_type, audience_id, ab_test_id, ab_test_variant_id, content_id.

Campaign / flow: campaign_id, flow_id, step_id, flow_version, flow_session_id, from_action_id, from_step_id, display_mode.

Display & rendering: display_method, method_to_display, orientation, paywall_request_duration_in_ms, paywall_display_time_in_ms, paywall_rendering_time_in_ms.

Offers: promo_offer, eligible_to_intro_offer, eligible_to_intro_offer_sk2, eligible_to_promo_offer, eligible_to_promo_offer_sk2.

Plan details: billing_plan_type, commitment, commitment_progress, storekit_version.

Select-options: selected_option_id, selected_options, displayed_options.

Session / installation: session_id, session_duration, session_count, app_installed_at, app_installed_at_ms, screen_duration, screen_displayed_at, screen_displayed_at_ms.

SDK lifecycle: is_sdk_started, sdk_start_error, sdk_start_duration_in_ms.

Web checkout: web_checkout_provider, web_checkout_url, client_reference_id, stripe_checkout_session_id, stripe_purchase_id.

Misc: error_code, event_created_at_ms_original, event_created_at_original.

Why optional

Each property only appears on the events that emit it (e.g. flow_* fields only on flow events). All additions are ?: T, matching the convention of placement_id, displayed_presentation, link_identifier, etc.

Change

packages/purchasely/src/types.ts — 51 lines added, 0 deleted. No runtime behavior change.

Test plan

  • yarn typecheck — passes
  • yarn lint — passes (0 errors)
  • yarn test — passes (types.test.ts 23/23)
  • CI green

🤖 Generated with Claude Code

…vent fields

The native iOS (PLYEventProperty.swift) and Android (PLYEventProperties.kt) SDKs
emit several event-context properties that were missing from the TypeScript
type, forcing consumers to cast `event.properties` to access them.

Adds all non-internal fields currently serialized by the native SDKs:
presentation context (is_fallback_presentation, presentation_type, audience_id,
ab_test_id / ab_test_variant_id, content_id), campaign / flow context
(campaign_id, flow_id, step_id, flow_version, flow_session_id, from_action_id,
from_step_id, display_mode), display / rendering metrics (display_method,
method_to_display, orientation, paywall_request_duration_in_ms,
paywall_display_time_in_ms, paywall_rendering_time_in_ms), offers
(promo_offer, eligible_to_intro_offer[_sk2], eligible_to_promo_offer[_sk2]),
plan details (billing_plan_type, commitment, commitment_progress,
storekit_version), select-options (selected_option_id, selected_options,
displayed_options), session / installation (session_id, session_duration,
session_count, app_installed_at[_ms], screen_duration,
screen_displayed_at[_ms]), SDK lifecycle (is_sdk_started, sdk_start_error,
sdk_start_duration_in_ms), web checkout (web_checkout_provider,
web_checkout_url, client_reference_id, stripe_checkout_session_id,
stripe_purchase_id), error_code, and the original event timestamps
(event_created_at_ms_original, event_created_at_original).

All added fields are optional (?:) since each property only appears on the
event types that emit it, matching the convention of placement_id (#240) and
the other existing fields.

Internal fields (`internal_*`) are intentionally excluded — they are marked
`internal` in the Kotlin model and are not part of the public event payload.

No runtime behavior change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 22, 2026

Greptile Summary

This PR completes PurchaselyEventProperties by adding 51 optional fields that the native Android and iOS SDKs already emit at runtime, eliminating the need for consumers to cast event.properties to access them. All additions are ?: T and there is no runtime behavior change.

  • Presentation & campaign context (is_fallback_presentation, presentation_type, audience_id, ab_test_*, campaign_id, flow_*, step_id, from_action_id, from_step_id) covers the fields fired on flow/placement events.
  • Display, timing & session metrics (paywall_*_time_in_ms, screen_duration, session_*, app_installed_at*) and web-checkout fields (web_checkout_provider, web_checkout_url, stripe_*) round out the event surface exposed to consumers.
  • Offer & plan details (promo_offer, eligible_to_*, billing_plan_type, commitment, storekit_version) and SDK lifecycle fields (is_sdk_started, sdk_start_*) mirror the corresponding native model properties.

Confidence Score: 4/5

Safe to merge — purely additive type declarations with no runtime impact.

All 51 additions are optional fields on an existing type, there are no breaking changes, and lint/typecheck/tests pass. The only things worth addressing before or after merge are using the existing PLYWebCheckoutProvider enum instead of string for web_checkout_provider, and adding a test block for the new properties per the project's own guidelines.

packages/purchasely/src/types.ts — the web_checkout_provider field type and the absence of new test assertions are both worth a look.

Important Files Changed

Filename Overview
packages/purchasely/src/types.ts Adds 51 optional fields to PurchaselyEventProperties; no runtime changes. web_checkout_provider is typed as string rather than the existing PLYWebCheckoutProvider enum, and no new tests cover the added fields.

Class Diagram

%%{init: {'theme': 'neutral'}}%%
classDiagram
    class PurchaselyEventProperties {
        +string sdk_version
        +PurchaselyEventsNames event_name
        +number event_created_at_ms
        +string event_created_at
        ...existing fields...
        +number? event_created_at_ms_original
        +string? event_created_at_original
    }
    class PresentationContext {
        <<new fields>>
        +boolean? is_fallback_presentation
        +string? presentation_type
        +string? audience_id
        +string? ab_test_id
        +string? ab_test_variant_id
        +string? content_id
    }
    class CampaignFlow {
        <<new fields>>
        +string? campaign_id
        +string? flow_id
        +string? step_id
        +string? flow_version
        +string? flow_session_id
        +string? from_action_id
        +string? from_step_id
    }
    class DisplayRendering {
        <<new fields>>
        +string? display_mode
        +string? display_method
        +string? orientation
        +number? paywall_request_duration_in_ms
        +number? paywall_display_time_in_ms
        +number? paywall_rendering_time_in_ms
    }
    class OffersAndPlans {
        <<new fields>>
        +string? promo_offer
        +boolean? eligible_to_intro_offer
        +boolean? eligible_to_promo_offer
        +string? billing_plan_type
        +string? commitment
        +string? storekit_version
    }
    class SessionInstallation {
        <<new fields>>
        +string? session_id
        +number? session_duration
        +number? session_count
        +string? app_installed_at
        +number? screen_duration
    }
    class WebCheckout {
        <<new fields>>
        +string? web_checkout_provider
        +string? web_checkout_url
        +string? client_reference_id
        +string? stripe_checkout_session_id
        +string? stripe_purchase_id
    }
    PurchaselyEventProperties --> PresentationContext : groups
    PurchaselyEventProperties --> CampaignFlow : groups
    PurchaselyEventProperties --> DisplayRendering : groups
    PurchaselyEventProperties --> OffersAndPlans : groups
    PurchaselyEventProperties --> SessionInstallation : groups
    PurchaselyEventProperties --> WebCheckout : groups
Loading

Fix All in Claude Code Fix All in Cursor Fix All in Codex

Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 2
packages/purchasely/src/types.ts:272
The `web_checkout_provider` field is typed as `string`, but `PLYWebCheckoutProvider` already exists in the codebase with exact string enum values (`'stripe'` | `'other'`) that match what the native SDK emits. Using the enum here would give consumers compile-time type safety and IDE autocomplete — the same pattern already used for `event_name: PurchaselyEventsNames`. If the native SDK can emit values outside of those two strings, `string` is fine, but that would be worth a comment.

```suggestion
  web_checkout_provider?: PLYWebCheckoutProvider;
```

### Issue 2 of 2
packages/purchasely/src/types.ts:226-276
**No test coverage for the 51 new fields**

The `AGENTS.md` guideline states "Add tests under `packages/purchasely/src/__tests__/` when adding public APIs or types." The existing `PurchaselyEvent` test at line 326 only exercises a handful of pre-existing properties; none of the fields added here are exercised. A consumer who assigns, say, `flow_id`, `stripe_purchase_id`, or `eligible_to_intro_offer` would get no compile-time evidence that the type accepts them correctly. Adding a test block that constructs a `PurchaselyEventProperties` object with at least a representative selection of the new fields would cover this.

Reviews (1): Last reviewed commit: "feat(types): complete PurchaselyEventPro..." | Re-trigger Greptile

sdk_start_error?: string;
sdk_start_duration_in_ms?: number;
error_code?: string;
web_checkout_provider?: string;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The web_checkout_provider field is typed as string, but PLYWebCheckoutProvider already exists in the codebase with exact string enum values ('stripe' | 'other') that match what the native SDK emits. Using the enum here would give consumers compile-time type safety and IDE autocomplete — the same pattern already used for event_name: PurchaselyEventsNames. If the native SDK can emit values outside of those two strings, string is fine, but that would be worth a comment.

Suggested change
web_checkout_provider?: string;
web_checkout_provider?: PLYWebCheckoutProvider;
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/purchasely/src/types.ts
Line: 272

Comment:
The `web_checkout_provider` field is typed as `string`, but `PLYWebCheckoutProvider` already exists in the codebase with exact string enum values (`'stripe'` | `'other'`) that match what the native SDK emits. Using the enum here would give consumers compile-time type safety and IDE autocomplete — the same pattern already used for `event_name: PurchaselyEventsNames`. If the native SDK can emit values outside of those two strings, `string` is fine, but that would be worth a comment.

```suggestion
  web_checkout_provider?: PLYWebCheckoutProvider;
```

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Cursor Fix in Codex

Comment on lines +226 to +276
event_created_at_ms_original?: number;
event_created_at_original?: string;
is_fallback_presentation?: boolean;
presentation_type?: string;
audience_id?: string;
ab_test_id?: string;
ab_test_variant_id?: string;
content_id?: string;
campaign_id?: string;
flow_id?: string;
step_id?: string;
flow_version?: string;
flow_session_id?: string;
from_action_id?: string;
from_step_id?: string;
display_mode?: string;
display_method?: string;
method_to_display?: string;
orientation?: string;
paywall_request_duration_in_ms?: number;
paywall_display_time_in_ms?: number;
paywall_rendering_time_in_ms?: number;
promo_offer?: string;
eligible_to_intro_offer?: boolean;
eligible_to_intro_offer_sk2?: boolean;
eligible_to_promo_offer?: boolean;
eligible_to_promo_offer_sk2?: boolean;
billing_plan_type?: string;
commitment?: string;
commitment_progress?: string;
storekit_version?: string;
selected_option_id?: string;
selected_options?: string[];
displayed_options?: string[];
session_id?: string;
session_duration?: number;
session_count?: number;
app_installed_at?: string;
app_installed_at_ms?: number;
screen_duration?: number;
screen_displayed_at?: string;
screen_displayed_at_ms?: number;
is_sdk_started?: boolean;
sdk_start_error?: string;
sdk_start_duration_in_ms?: number;
error_code?: string;
web_checkout_provider?: string;
web_checkout_url?: string;
client_reference_id?: string;
stripe_checkout_session_id?: string;
stripe_purchase_id?: string;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 No test coverage for the 51 new fields

The AGENTS.md guideline states "Add tests under packages/purchasely/src/__tests__/ when adding public APIs or types." The existing PurchaselyEvent test at line 326 only exercises a handful of pre-existing properties; none of the fields added here are exercised. A consumer who assigns, say, flow_id, stripe_purchase_id, or eligible_to_intro_offer would get no compile-time evidence that the type accepts them correctly. Adding a test block that constructs a PurchaselyEventProperties object with at least a representative selection of the new fields would cover this.

Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/purchasely/src/types.ts
Line: 226-276

Comment:
**No test coverage for the 51 new fields**

The `AGENTS.md` guideline states "Add tests under `packages/purchasely/src/__tests__/` when adding public APIs or types." The existing `PurchaselyEvent` test at line 326 only exercises a handful of pre-existing properties; none of the fields added here are exercised. A consumer who assigns, say, `flow_id`, `stripe_purchase_id`, or `eligible_to_intro_offer` would get no compile-time evidence that the type accepts them correctly. Adding a test block that constructs a `PurchaselyEventProperties` object with at least a representative selection of the new fields would cover this.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code Fix in Cursor Fix in Codex

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant