Speakable schema fragment or empty array. */ public function generate( \WC_Product $product ): array { $css_selectors = $this->get_css_selectors( $product ); if ( empty( $css_selectors ) ) { return array(); } $speakable = array( '@type' => 'SpeakableSpecification', 'cssSelector' => $css_selectors, ); /** * Filters the Speakable schema fragment. * * @param array $speakable The speakable spec. * @param \WC_Product $product The product. */ return apply_filters( 'aicommerce_speakable_schema', $speakable, $product ); } /** * Get CSS selectors for speakable content regions. * * Targets the most important product information that voice assistants * should prioritize reading aloud. * * @param \WC_Product $product The product. * * @return array CSS selectors. */ private function get_css_selectors( \WC_Product $product ): array { $selectors = array(); // Product title — always speakable. $selectors[] = '.product_title'; // Short description — concise summary suitable for voice. if ( ! empty( $product->get_short_description() ) ) { $selectors[] = '.woocommerce-product-details__short-description'; } // Price — important for voice commerce queries. $selectors[] = '.price'; /** * Filters the CSS selectors used for Speakable content. * * Theme authors can add/modify selectors to match their markup. * * @param array $selectors CSS selector list. * @param \WC_Product $product The product. */ return apply_filters( 'aicommerce_speakable_selectors', $selectors, $product ); } /** * Generate a text-based speakable summary for the product. * * Used when CSS selectors are not appropriate (e.g., for feeds). * * @param \WC_Product $product The product. * * @return string A voice-optimized product summary. */ public function generate_text_summary( \WC_Product $product ): string { $parts = array(); $parts[] = $product->get_name(); $short_desc = wp_strip_all_tags( $product->get_short_description() ); if ( ! empty( $short_desc ) ) { $parts[] = $short_desc; } $price = $product->get_price(); if ( '' !== $price ) { $parts[] = sprintf( /* translators: 1: Price 2: Currency */ __( 'Priced at %1$s %2$s.', 'ai-discoverability-kit' ), $price, get_woocommerce_currency() ); } $stock = $product->get_stock_status(); if ( 'instock' === $stock ) { $parts[] = __( 'Currently in stock.', 'ai-discoverability-kit' ); } elseif ( 'outofstock' === $stock ) { $parts[] = __( 'Currently out of stock.', 'ai-discoverability-kit' ); } return implode( ' ', $parts ); } }