Skip to content

epic-2/story-2: Support Revenue Data and Tracking Payload Construction - #30

Closed
usmanabbas7 wants to merge 7 commits into
epic-2/story-1-track-conversions-from-a-visitor-contextfrom
epic-2/story-2-support-revenue-data-and-tracking-payload-construction
Closed

epic-2/story-2: Support Revenue Data and Tracking Payload Construction#30
usmanabbas7 wants to merge 7 commits into
epic-2/story-1-track-conversions-from-a-visitor-contextfrom
epic-2/story-2-support-revenue-data-and-tracking-payload-construction

Conversation

@usmanabbas7

Copy link
Copy Markdown
Collaborator

Summary

Extends Story 2.1's tracking slice with revenue + conversion attributes and owns raw outbound payload assembly (tracking/payloads.py) matching the verbose JS-SDK wire contract. Stops before batching/dedup/queue/flush/network (Story 2.3/2.4 territory).

Audit findings honored: F-001 (no goalKey/timestamp/conversionData in the wire event — ConversionEvent type per types.gen.ts:2502-2530), F-002 (enrichData computed from DataStore presence, not hardcoded; source: "js-sdk" fallback until python-sdk is confirmed in the backend allowlist).

Tests: 230 → 268 (+38), full suite green (uv run pytest).

Traceability

Notes for reviewer

  • Readiness gate: PASS 9/10 with 4 auto-delegated questions (sprint mode): attribution computed on-demand from snapshot; source="js-sdk" fallback (F-002); computed enrichData (F-002); wire event field set per F-001. See conductor's readiness-assessment.md for details.
  • Code review: clean after round 2 (R1 found the VisitorSegments allowlist parity issue, fixed in 021044d).
  • Story file carries stale pre-audit prose (Task 3.3 goalKey/timestamp; Dev Notes source: python-sdk/enrichData: true) that contradicts the audit-patched AC feat(python-sdk): add in-memory config evaluation managers #2 / Task 3.2 — the patched text was followed.

🤖 Generated with Claude Code

@usmanabbas7 usmanabbas7 self-assigned this Jun 7, 2026
@usmanabbas7
usmanabbas7 requested a review from clllaur June 7, 2026 12:43

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request implements Story 2.2 of the Convert Python SDK, extending the conversion tracking functionality to support optional revenue, custom conversion data, and visitor attribution context (active segments and variation assignments). It introduces the tracking/payloads.py module to map internal snake_case conversion events to the verbose JS-SDK wire contract, along with dedicated tracking error classes and comprehensive test coverage. The review feedback suggests several improvements: passing location_attributes through the conversion creation and bucketing evaluation pipeline to support location-targeted experiences, validating that conversion_data is a mapping to prevent potential AttributeErrors, and validating that revenue is a valid number (and not a boolean) to fail fast on programmer misuse.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines 270 to 277
return create_conversion(
self._snapshot,
visitor_id=self._state.visitor_id,
goal_key=goal_key,
revenue=revenue,
conversion_data=conversion_data,
visitor_attributes=self._state.visitor_attributes,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

To ensure that experiences with location-targeting rules are correctly evaluated and attributed at conversion time, the context's location_attributes should be passed to create_conversion.

Suggested change
return create_conversion(
self._snapshot,
visitor_id=self._state.visitor_id,
goal_key=goal_key,
revenue=revenue,
conversion_data=conversion_data,
visitor_attributes=self._state.visitor_attributes,
)
return create_conversion(
self._snapshot,
visitor_id=self._state.visitor_id,
goal_key=goal_key,
revenue=revenue,
conversion_data=conversion_data,
visitor_attributes=self._state.visitor_attributes,
location_attributes=self._location_attributes,
)

Comment on lines +64 to +69
def _compute_bucketing_assignments(
snapshot: "ConfigSnapshot",
*,
visitor_id: str,
visitor_attributes: Optional[Mapping[str, Any]],
) -> Dict[str, str]:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Add location_attributes to _compute_bucketing_assignments so that location-targeted experiences can be correctly evaluated.

def _compute_bucketing_assignments(
    snapshot: "ConfigSnapshot",
    *,
    visitor_id: str,
    visitor_attributes: Optional[Mapping[str, Any]],
    location_attributes: Optional[Mapping[str, Any]] = None,
) -> Dict[str, str]:

Comment on lines +88 to +93
result = select_experience(
str(key),
snapshot,
visitor_id=visitor_id,
visitor_attributes=visitor_attributes,
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Pass location_attributes to select_experience to ensure location rules are evaluated during conversion-time bucketing attribution.

        result = select_experience(
            str(key),
            snapshot,
            visitor_id=visitor_id,
            visitor_attributes=visitor_attributes,
            location_attributes=location_attributes,
        )

Comment on lines 99 to 107
def create_conversion(
snapshot: "ConfigSnapshot",
*,
visitor_id: str,
goal_key: str,
revenue: Optional[float] = None,
conversion_data: Optional[Mapping[str, Any]] = None,
visitor_attributes: Optional[Mapping[str, Any]] = None,
) -> ConversionResult:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Add location_attributes to create_conversion signature to support passing location context from the visitor session.

def create_conversion(
    snapshot: "ConfigSnapshot",
    *,
    visitor_id: str,
    goal_key: str,
    revenue: Optional[float] = None,
    conversion_data: Optional[Mapping[str, Any]] = None,
    visitor_attributes: Optional[Mapping[str, Any]] = None,
    location_attributes: Optional[Mapping[str, Any]] = None,
) -> ConversionResult:

Comment on lines +157 to +159
bucketing_assignments = _compute_bucketing_assignments(
snapshot, visitor_id=visitor_id, visitor_attributes=visitor_attributes
)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Pass location_attributes to _compute_bucketing_assignments.

    bucketing_assignments = _compute_bucketing_assignments(
        snapshot,
        visitor_id=visitor_id,
        visitor_attributes=visitor_attributes,
        location_attributes=location_attributes,
    )

Comment on lines +54 to +56
if not conversion_data:
return
for key, value in conversion_data.items():

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Ensure conversion_data is a mapping before checking if it is empty or iterating over its items, to prevent unhandled AttributeError if a non-mapping (like a list or string) is passed.

Suggested change
if not conversion_data:
return
for key, value in conversion_data.items():
if conversion_data is None:
return
if not isinstance(conversion_data, Mapping):
raise ConversionDataError(
"conversion_data",
reason="value must be a dictionary/mapping",
)
if not conversion_data:
return
for key, value in conversion_data.items():

Comment on lines +131 to +132
# Fail fast on programmer misuse before any goal resolution (AC#3).
_validate_conversion_data(conversion_data)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Validate that revenue is a valid number (and not a boolean) to fail fast on programmer misuse, matching the documented behavior of ConversionDataError.

    # Fail fast on programmer misuse before any goal resolution (AC#3).
    if revenue is not None and (not isinstance(revenue, (int, float)) or isinstance(revenue, bool)):
        raise ConversionDataError(
            "revenue",
            reason="value must be a number (int or float)",
        )
    _validate_conversion_data(conversion_data)

usmanabbas7 and others added 7 commits June 14, 2026 21:58
Beads: ai-driven-product-dev-f05o

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… implementation (GREEN)

Beads: ai-driven-product-dev-f05o

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…tests (RED)

Beads: ai-driven-product-dev-se3u

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…implementation (GREEN)

Beads: ai-driven-product-dev-se3u

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Beads: ai-driven-product-dev-tg8a

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Beads: ai-driven-product-dev-tg8a

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Beads: ai-driven-product-dev-d2tg

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@usmanabbas7
usmanabbas7 force-pushed the epic-2/story-1-track-conversions-from-a-visitor-context branch from e5af437 to 4c2b98b Compare June 14, 2026 16:58
@usmanabbas7
usmanabbas7 force-pushed the epic-2/story-2-support-revenue-data-and-tracking-payload-construction branch from 021044d to 7cf6b2f Compare June 14, 2026 16:58
@abbaseya

Copy link
Copy Markdown
Collaborator

Superseded — all commits already in main (bc76b64). Closing without merge as part of post-sprint cleanup.

@abbaseya abbaseya closed this Jun 18, 2026
@abbaseya
abbaseya deleted the epic-2/story-2-support-revenue-data-and-tracking-payload-construction branch June 18, 2026 16:31
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.

2 participants