• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Yoast / wordpress-seo / 15936d2b846c322fa3b4b91e32ba3f7c002a45a6

13 May 2025 08:35AM UTC coverage: 58.702% (+0.06%) from 58.644%
15936d2b846c322fa3b4b91e32ba3f7c002a45a6

Pull #22258

github

web-flow
Merge pull request #22254 from Yoast/fix/ai-optimize-woo-upsell

Adds an upsell for AI Optimize on products
Pull Request #22258: Merges the feature branch `feature/ai-optimize-classic` to `trunk`

8175 of 14231 branches covered (57.45%)

Branch coverage included in aggregate %.

37 of 68 new or added lines in 11 files covered. (54.41%)

3 existing lines in 2 files now uncovered.

14070 of 23664 relevant lines covered (59.46%)

100886.47 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

5.66
/packages/js/src/ai-generator/components/modal-content.js
1
import { useDispatch, useSelect } from "@wordpress/data";
2
import { useMemo } from "@wordpress/element";
3
import { AiGenerateTitlesAndDescriptionsUpsell } from "../../shared-admin/components";
4
import { __, sprintf } from "@wordpress/i18n";
5

6
const STORE = "yoast-seo/editor";
2✔
7

8
/**
9
 * The upsell props.
10
 * @typedef {Object} UpsellProps
11
 * @property {string} upsellLink The URL for the upsell.
12
 * @property {string} [upsellLabel] The label for the upsell.
13
 * @property {string} [newToText] The "new to" text for the upsell.
14
 * @property {JSX.Element} [bundleNote] A note about the bundle upsell.
15
 * @property {string} [ctbId] The CTB ID for the upsell.
16
 * @property {boolean} [isProductCopy] Whether the upsell is for product copy.
17
 */
18

19
/**
20
 * Retrieves the upsell props based on the active licenses.
21
 * @param {Object} upsellLinks An object containing the upsell links and their associated data.
22
 * @param {string} upsellLinks.premium The Yoast SEO Premium upsell link .
23
 * @param {string} upsellLinks.woo The Yoast WooCommerce SEO upsell link.
24
 * @param {string} upsellLinks.bundle The bundle upsell link.
25
 * @returns {UpsellProps} The upsell props.
26
 */
27
export const getUpsellProps = ( upsellLinks ) => {
2✔
28
        const isPremiumActive = useSelect( select => select( STORE ).getIsPremium(), [] );
×
29
        const isWooSeoActive = useSelect( select => select( STORE ).getIsWooSeoActive(), [] );
×
30
        const isWooCommerceActive = useSelect( select => select( STORE ).getIsWooCommerceActive(), [] );
×
31

32
        const isProductPost = useSelect( select => select( STORE ).getIsProduct(), [] );
×
33
        const isProductTerm = useSelect( select => select( STORE ).getIsProductTerm(), [] );
×
34

35
        const upsellProps = {
×
36
                upsellLink: upsellLinks.premium,
37
                // The default ctbId is passed as a prop to the AiGenerateTitlesAndDescriptionsUpsell component.
38
        };
39

40
        // Use specific copy for product posts and terms, otherwise revert to the defaults.
41
        if ( isWooCommerceActive && ( isProductPost || isProductTerm ) ) {
×
42
                const upsellPremiumWooLabel = sprintf(
×
43
                        /* translators: %1$s expands to Yoast SEO Premium, %2$s expands to Yoast WooCommerce SEO. */
44
                        __( "%1$s + %2$s", "wordpress-seo" ),
45
                        "Yoast SEO Premium",
46
                        "Yoast WooCommerce SEO"
47
                );
48
                upsellProps.newToText = sprintf(
×
49
                        /* translators: %1$s expands to Yoast SEO Premium and Yoast WooCommerce SEO. */
50
                        __( "New in %1$s", "wordpress-seo" ),
51
                        upsellPremiumWooLabel
52
                );
53

54
                if ( isPremiumActive ) {
×
55
                        upsellProps.upsellLabel = sprintf(
×
56
                                /* translators: %1$s expands to Yoast WooCommerce SEO. */
57
                                __( "Unlock with %1$s", "wordpress-seo" ),
58
                                "Yoast WooCommerce SEO"
59
                        );
NEW
60
                        upsellProps.upsellLink = upsellLinks.woo;
×
61
                        upsellProps.ctbId = "5b32250e-e6f0-44ae-ad74-3cefc8e427f9";
×
62
                } else if ( ! isWooSeoActive ) {
×
63
                        upsellProps.upsellLabel = `${sprintf(
×
64
                                /* translators: %1$s expands to Woo Premium bundle. */
65
                                __( "Unlock with the %1$s", "wordpress-seo" ),
66
                                "Woo Premium bundle"
67
                        )}*`;
68
                        upsellProps.bundleNote = <div className="yst-text-xs yst-text-slate-500 yst-mt-2">
×
69
                                { `*${upsellPremiumWooLabel}` }
70
                        </div>;
NEW
71
                        upsellProps.upsellLink = upsellLinks.bundle;
×
72
                        upsellProps.ctbId = "c7e7baa1-2020-420c-a427-89701700b607";
×
73
                }
74
        }
NEW
75
        return upsellProps;
×
76
};
77

78
/**
79
 * @returns {JSX.Element} The element.
80
 */
81
export const ModalContent = () => {
2✔
NEW
82
        const upsellLinks = {
×
NEW
83
                premium: useSelect( select => select( STORE ).selectLink( "https://yoa.st/ai-generator-upsell" ), [] ),
×
NEW
84
                bundle: useSelect( select => select( STORE ).selectLink( "https://yoa.st/ai-generator-upsell-woo-seo-premium-bundle" ), [] ),
×
NEW
85
                woo: useSelect( select => select( STORE ).selectLink( "https://yoa.st/ai-generator-upsell-woo-seo" ), [] ),
×
86
        };
87

NEW
88
        const upsellProps = getUpsellProps( upsellLinks );
×
89

90
        // Use specific copy for product posts.
NEW
91
        const isWooCommerceActive = useSelect( select => select( STORE ).getIsWooCommerceActive(), [] );
×
NEW
92
        const isProductPost = useSelect( select => select( STORE ).getIsProduct(), [] );
×
93

NEW
94
        if ( isWooCommerceActive && isProductPost ) {
×
NEW
95
                upsellProps.title = __( "Generate product titles & descriptions with AI!", "wordpress-seo" );
×
NEW
96
                upsellProps.isProductCopy = true;
×
97
        }
98

NEW
99
        const learnMoreLink = useSelect( select => select( STORE ).selectLink( "https://yoa.st/ai-generator-learn-more" ), [] );
×
100

101
        const imageLink = useSelect( select => select( STORE ).selectImageLink( "ai-generator-preview.png" ), [] );
×
102
        const thumbnail = useMemo( () => ( {
×
103
                src: imageLink,
104
                width: "432",
105
                height: "244",
106
        } ), [ imageLink ] );
107

108
        const value = useSelect( select => select( STORE ).selectWistiaEmbedPermissionValue(), [] );
×
109
        const status = useSelect( select => select( STORE ).selectWistiaEmbedPermissionStatus(), [] );
×
110
        const { setWistiaEmbedPermission: set } = useDispatch( STORE );
×
111
        const wistiaEmbedPermission = useMemo( () => ( { value, status, set } ), [ value, status, set ] );
×
112

113
        return (
×
114
                <AiGenerateTitlesAndDescriptionsUpsell
115
                        learnMoreLink={ learnMoreLink }
116
                        thumbnail={ thumbnail }
117
                        wistiaEmbedPermission={ wistiaEmbedPermission }
118
                        { ...upsellProps }
119
                />
120
        );
121
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc