ID ); } $t = Store::table(); $placeholders = implode( ',', array_fill( 0, count( $keys ), '%s' ) ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- table name and a list of %s placeholders. return (array) $wpdb->get_results( $wpdb->prepare( "SELECT * FROM $t WHERE customer_key IN ($placeholders)", $keys ), ARRAY_A ); } /** * Registers the exporter. * * @param array $exporters Exporters. * @return array */ public static function register_exporter( $exporters ) { $exporters['statbird'] = array( 'exporter_friendly_name' => __( 'Statbird customer analytics', 'statbird' ), 'callback' => array( __CLASS__, 'export' ), ); return $exporters; } /** * Exports what Statbird holds about an email. * * @param string $email Email. * @return array */ public static function export( $email ) { $groups = Scoring::groups(); $items = array(); foreach ( self::rows( $email ) as $r ) { $items[] = array( 'group_id' => 'statbird', 'group_label' => __( 'Customer analytics', 'statbird' ), 'item_id' => 'statbird-' . $r['customer_key'], 'data' => array( array( 'name' => __( 'Customer group', 'statbird' ), 'value' => $groups[ $r['segment'] ]['label'] ?? $r['segment'], ), array( 'name' => __( 'Orders', 'statbird' ), 'value' => $r['orders'], ), array( 'name' => __( 'Total spent', 'statbird' ), 'value' => $r['spent'], ), array( 'name' => __( 'First order', 'statbird' ), 'value' => $r['first_order'], ), array( 'name' => __( 'Last order', 'statbird' ), 'value' => $r['last_order'], ), array( 'name' => __( 'Churn risk', 'statbird' ), 'value' => $r['churn_risk'] . '%', ), array( 'name' => __( 'Recency, frequency, monetary scores', 'statbird' ), 'value' => $r['r'] . ' / ' . $r['f'] . ' / ' . $r['m'], ), ), ); } return array( 'data' => $items, 'done' => true, ); } /** * Registers the eraser. * * @param array $erasers Erasers. * @return array */ public static function register_eraser( $erasers ) { $erasers['statbird'] = array( 'eraser_friendly_name' => __( 'Statbird customer analytics', 'statbird' ), 'callback' => array( __CLASS__, 'erase' ), ); return $erasers; } /** * Erases Statbird's rows for an email. They would be rebuilt from orders that still exist, * so erase the orders too (WooCommerce does this when its own erasure is enabled). * * @param string $email Email. * @return array */ public static function erase( $email ) { global $wpdb; $removed = 0; foreach ( self::rows( $email ) as $r ) { Store::delete( $r['customer_key'] ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching $wpdb->delete( Changes::table(), array( 'customer_key' => $r['customer_key'] ), array( '%s' ) ); ++$removed; } return array( 'items_removed' => $removed, 'items_retained' => false, 'messages' => $removed ? array( __( 'Statbird analytics removed. They will be recalculated from any orders that are kept.', 'statbird' ) ) : array(), 'done' => true, ); } /** * Suggested privacy policy text. */ public static function policy_text() { if ( ! function_exists( 'wp_add_privacy_policy_content' ) ) { return; } wp_add_privacy_policy_content( 'Statbird', wp_kses_post( '

' . __( 'We analyse past orders to understand our customers, for example how often they buy and whether they are likely to buy again. This analysis stays on this website. It is based on order data we already hold and is not shared with anyone.', 'statbird' ) . '

' . '

' . __( 'If the store uses AI insights, summary statistics about customer groups (not names or contact details, unless the store owner enables that) are sent to the AI provider the store owner has connected.', 'statbird' ) . '

' ) ); } }