*/ const LANDING_VARIANTS = array( array( 'key' => 'indie', 'rollout' => 50, ), array( 'key' => 'free-plus', 'rollout' => 50, ), ); /** * Build the feature-flag bootstrap map for the landing page. * * Returns a map of resolved flags keyed for PostHog's `bootstrap.featureFlags` * (e.g. `array( 'landing-variant' => 'indie' )`). Empty when no distinct id is * available, in which case the bundle resolves the variant itself. * * @param string $distinct_id Stable anonymous identifier for the visitor/site. * * @return array */ public function get_landing_bootstrap_flags( string $distinct_id ): array { $flags = array(); $variant = $this->get_landing_variant( $distinct_id ); if ( null !== $variant ) { $flags[ self::LANDING_FLAG_KEY ] = $variant; } /** * Filters the feature flags bootstrapped into the landing page. * * Allows forcing a variant (for QA) or extending the bootstrap with * additional flags. Values must be strings or booleans, matching * PostHog's `bootstrap.featureFlags` contract. * * @since 1.9.7 * * @param array $flags Resolved flag map. * @param string $distinct_id The visitor distinct id. */ return apply_filters( 'woocommerce_pos_landing_bootstrap_flags', $flags, $distinct_id ); } /** * Resolve the `landing-variant` value for a distinct id. * * @param string $distinct_id Stable anonymous identifier. * * @return null|string The variant key, or null when no distinct id is given. */ public function get_landing_variant( string $distinct_id ): ?string { if ( '' === $distinct_id ) { return null; } return $this->match_variant( self::LANDING_FLAG_KEY, $distinct_id, self::LANDING_VARIANTS ); } /** * Map a distinct id to a variant using PostHog's consistent-hash lookup. * * The variant hash is salted with `variant` and compared against the * cumulative rollout ranges built from the variant order. * * @param string $key Flag key. * @param string $distinct_id Distinct id. * @param array $variants Ordered variants. * * @return null|string */ private function match_variant( string $key, string $distinct_id, array $variants ): ?string { $hash_value = $this->hash( $key, $distinct_id, 'variant' ); $value_min = 0.0; foreach ( $variants as $variant ) { $value_max = $value_min + ( $variant['rollout'] / 100 ); if ( $hash_value >= $value_min && $hash_value < $value_max ) { return $variant['key']; } $value_min = $value_max; } return null; } /** * PostHog consistent hash: SHA-1 of `key.distinct_id+salt`, first 15 hex * digits scaled to a deterministic [0, 1) float. * * @param string $key Flag key. * @param string $distinct_id Distinct id. * @param string $salt Hash salt (`variant` for variant selection). * * @return float */ private function hash( string $key, string $distinct_id, string $salt = '' ): float { $hex = substr( sha1( $key . '.' . $distinct_id . $salt ), 0, 15 ); return (float) ( hexdec( $hex ) / self::LONG_SCALE ); } }