@@ -416,6 +416,7 @@ def run_experience(
416416 * ,
417417 attributes : Optional [Mapping [str , Any ]] = None ,
418418 location_attributes : Optional [Mapping [str , Any ]] = None ,
419+ enable_tracking : bool = True ,
419420 ) -> Optional [ExperienceResult ]:
420421 """Evaluate a single experience by key for this visitor.
421422
@@ -425,6 +426,19 @@ def run_experience(
425426 qualifies and buckets into a variation, or ``None`` for any normal miss
426427 (missing experience, unqualified visitor, no active variation). Never
427428 raises for normal evaluation outcomes and performs no network I/O.
429+
430+ Args:
431+ experience_key: The experience key to evaluate.
432+ attributes: Optional per-call visitor attribute overlay (ephemeral).
433+ location_attributes: Optional per-call location attribute overlay
434+ (ephemeral).
435+ enable_tracking: When ``True`` (the default), a successfully-bucketed
436+ result enqueues a bucketing activation event via the tracker
437+ (Story 2.5). When ``False``, no bucketing event is enqueued and
438+ no ``LifecycleEvent.BUCKETING`` is emitted. The returned
439+ :class:`~convert_sdk.domain.results.ExperienceResult` is
440+ identical regardless of this flag — it gates tracking only, not
441+ evaluation. Must be passed as a keyword argument.
428442 """
429443 visitor_attributes = self ._state .with_overlay (attributes )
430444 location = self ._merge (self ._location_attributes , location_attributes )
@@ -436,20 +450,36 @@ def run_experience(
436450 location_attributes = location ,
437451 )
438452 self ._log_bucketing (result )
453+ if result is not None and enable_tracking and self ._tracker is not None :
454+ self ._tracker .track_bucketing (
455+ visitor_id = self ._state .visitor_id ,
456+ experience_id = result .experience_id ,
457+ variation_id = result .variation_id ,
458+ )
439459 return result
440460
441461 def run_experiences (
442462 self ,
443463 * ,
444464 attributes : Optional [Mapping [str , Any ]] = None ,
445465 location_attributes : Optional [Mapping [str , Any ]] = None ,
466+ enable_tracking : bool = True ,
446467 ) -> List [ExperienceResult ]:
447468 """Evaluate all applicable experiences for this visitor.
448469
449470 Returns the list of typed results for the experiences the visitor
450471 qualifies for and buckets into; experiences that do not resolve are
451472 omitted (no ``None`` entries). Evaluation stays local to the snapshot —
452473 no network I/O.
474+
475+ Args:
476+ attributes: Optional per-call visitor attribute overlay (ephemeral).
477+ location_attributes: Optional per-call location attribute overlay
478+ (ephemeral).
479+ enable_tracking: When ``True`` (the default), each successfully-bucketed
480+ result enqueues a bucketing activation event via the tracker
481+ (Story 2.5). When ``False``, no bucketing events are enqueued
482+ for any resolved experience. Must be passed as a keyword argument.
453483 """
454484 visitor_attributes = self ._state .with_overlay (attributes )
455485 location = self ._merge (self ._location_attributes , location_attributes )
@@ -468,6 +498,12 @@ def run_experiences(
468498 if result is not None :
469499 results .append (result )
470500 self ._log_bucketing (result )
501+ if enable_tracking and self ._tracker is not None :
502+ self ._tracker .track_bucketing (
503+ visitor_id = self ._state .visitor_id ,
504+ experience_id = result .experience_id ,
505+ variation_id = result .variation_id ,
506+ )
471507 return results
472508
473509 # --- feature resolution ------------------------------------------------
0 commit comments