session || ! method_exists( WC()->session, 'get_customer_id' ) ) { return ''; } return (string) WC()->session->get_customer_id(); } /** * Releve l'oppref de l'adresse d'atterrissage et le pousse a Convrail, sans bloquer la page. * * @return void */ public static function capture_landing() { if ( is_admin() || wp_doing_ajax() || wp_doing_cron() || ( defined( 'REST_REQUEST' ) && REST_REQUEST ) ) { return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- parametre d'atterrissage publicitaire, lu et nettoye, jamais execute. $oppref = isset( $_GET['oppref'] ) ? sanitize_text_field( wp_unslash( $_GET['oppref'] ) ) : ''; if ( '' === $oppref ) { // Cas de presque toutes les pages vues : rien a faire, et rien a calculer. return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- parametres UTM d'atterrissage, lus et nettoyes. $utm = array_map( 'sanitize_text_field', wp_unslash( array_intersect_key( $_GET, array_flip( array( 'utm_source', 'utm_medium', 'utm_campaign' ) ) ) ) ); self::record( $oppref, esc_url_raw( home_url( add_query_arg( array() ) ) ), isset( $_SERVER['HTTP_REFERER'] ) ? esc_url_raw( wp_unslash( $_SERVER['HTTP_REFERER'] ) ) : null, $utm, false ); } /** * Session d'atterrissage signalee par le pixel, pour les pages servies depuis un cache. * * Sans jeton de securite, et c'est voulu: la page qui l'appelle sort d'un cache, un jeton y * serait perime pour tous les visiteurs suivants. Rien de sensible ne passe par ici. La session * enregistree est toujours celle du visiteur qui appelle (son propre cookie WooCommerce), il ne * peut pas ecrire sur celle d'un autre ; l'adresse d'arrivee n'est retenue que si elle est sur * ce site. * * @return void */ public static function capture_from_browser() { // phpcs:disable WordPress.Security.NonceVerification.Missing -- point d'entree public sans privilege, voir ci-dessus. $oppref = isset( $_POST['oppref'] ) ? sanitize_text_field( wp_unslash( $_POST['oppref'] ) ) : ''; $landing = isset( $_POST['landing_url'] ) ? esc_url_raw( wp_unslash( $_POST['landing_url'] ) ) : ''; $referrer = isset( $_POST['referrer'] ) ? esc_url_raw( wp_unslash( $_POST['referrer'] ) ) : ''; // phpcs:enable WordPress.Security.NonceVerification.Missing if ( ! self::is_own_url( $landing ) ) { $landing = ''; } $recorded = self::record( $oppref, '' !== $landing ? $landing : null, '' !== $referrer ? $referrer : null, self::utm_from( $landing ), true ); wp_send_json( array( 'recorded' => $recorded ), $recorded ? 202 : 200 ); } /** * Enregistre la session chez Convrail. Vrai si un envoi est parti. * * @param string $oppref Identifiant de clic ChatGPT Ads, tel que recu. * @param string|null $landing Page d'arrivee. * @param string|null $referrer Page precedente. * @param array $utm utm_source, utm_medium, utm_campaign. * @param bool $blocking Attendre la reponse (requete AJAX) ou non (page visitee). * @return bool */ private static function record( $oppref, $landing, $referrer, $utm, $blocking ) { if ( '' === $oppref || strlen( $oppref ) > 512 || ! Convrail_Client::is_connected() ) { return false; } if ( ! function_exists( 'WC' ) || ! WC()->session ) { return false; } /* * WooCommerce ne pose son cookie de session qu'au premier ajout au panier. Un visiteur * venu de ChatGPT qui regarde avant d'acheter n'en aurait donc pas encore, et la commande * ne pourrait pas etre recollee. On demande a WooCommerce de le poser maintenant: c'est * SON cookie, necessaire au panier, pas un cookie de suivi a nous. */ if ( method_exists( WC()->session, 'set_customer_session_cookie' ) ) { WC()->session->set_customer_session_cookie( true ); } $session_id = self::current_session_id(); if ( '' === $session_id ) { return false; } $payload = array( 'session_id' => substr( $session_id, 0, 64 ), 'oppref' => $oppref, 'landing_url' => $landing, 'referrer' => $referrer, 'utm_source' => isset( $utm['utm_source'] ) ? $utm['utm_source'] : null, 'utm_medium' => isset( $utm['utm_medium'] ) ? $utm['utm_medium'] : null, 'utm_campaign' => isset( $utm['utm_campaign'] ) ? $utm['utm_campaign'] : null, ); if ( $blocking ) { // Requete AJAX en tache de fond: personne n'attend, on peut lire la reponse. Convrail_Client::post( '/bridge/wc/sessions', $payload, true, 5 ); } else { Convrail_Client::post_async( '/bridge/wc/sessions', $payload ); } return true; } /** * Vrai si l'adresse est sur ce site. On n'enregistre jamais la page d'un autre domaine comme * page d'arrivee, quoi qu'envoie le navigateur. * * @param string $url Adresse a verifier. * @return bool */ private static function is_own_url( $url ) { if ( '' === (string) $url ) { return false; } $host = wp_parse_url( $url, PHP_URL_HOST ); $home = wp_parse_url( home_url(), PHP_URL_HOST ); return is_string( $host ) && is_string( $home ) && strtolower( $host ) === strtolower( $home ); } /** * Parametres UTM d'une adresse. * * @param string $url Adresse d'arrivee. * @return array */ private static function utm_from( $url ) { $query = wp_parse_url( (string) $url, PHP_URL_QUERY ); if ( ! is_string( $query ) || '' === $query ) { return array(); } $params = array(); wp_parse_str( $query, $params ); $utm = array(); foreach ( array( 'utm_source', 'utm_medium', 'utm_campaign' ) as $key ) { if ( isset( $params[ $key ] ) && is_string( $params[ $key ] ) && '' !== $params[ $key ] ) { $utm[ $key ] = sanitize_text_field( $params[ $key ] ); } } return $utm; } }