Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multichannel Marketing - API #36222

Conversation

nima-karimi
Copy link
Contributor

@nima-karimi nima-karimi commented Dec 28, 2022

All Submissions:

Changes proposed in this Pull Request:

This PR implements four new APIs for the marketing dashboard:

1. GET /wp-json/wc-admin/marketing/recommendations

Returns an array of recommended marketing channels and extensions. It accepts a category parameter that can be set to either channels or extensions.

This API obtains the list of recommended extensions from the GET https://woocommerce.com/wp-json/wccom/marketing-tab/1.2/recommendations.json API and filters the results based on their category and subcategories:

A) channels - Any recommended extension with the category of "marketing" and the subcategory of "sales-channel" will be included in the response.
B) extensions - Any recommended extension with the category of "marketing" but WITHOUT the subcategory of "sales-channel" will be included in the response. This means that the response will include the list of all marketing extensions and plugins recommended by the WooCommerce store API EXCEPT marketing channels.

The response schema is a mirror of WooCommerce.com's GET https://woocommerce.com/wp-json/wccom/marketing-tab/1.2/recommendations.json API.

2. GET /wp-json/wc-admin/marketing/channels

Returns an array of registered marketing channels.

Example Response:

[
    {
        "slug": "google-listings-and-ads",
        "is_setup_completed": true,
        "settings_url": "https://example.org/wp-admin/admin.php?page=wc-admin&path=/google/settings",
        "name": "Google Listings & Ads",
        "description": "Native integration with Google that allows merchants to easily display their products across Google’s network.",
        "product_listings_status": "synced",
        "errors_count": 0,
        "icon": "https://woocommerce.com/wp-content/uploads/2021/06/woo-GoogleListingsAds-jworee.png"
    }
]

3. GET /wp-json/wc-admin/marketing/campaigns

Returns an aggregated list of marketing campaigns for all registered marketing channels. This API returns a paginated response and accepts the following two parameters:

  • page
  • per_page

Example Response:

[
    {
        "id": "1",
        "channel": "google-listings-and-ads",
        "title": "11",
        "manage_url": "https://example.org/wp-admin/admin.php?page=wc-admin&path=/google/settings&subpath=/campaigns/edit",
        "cost": {
            "value": "100",
            "currency": "USD"
        }
    },
    {
        "id": "2",
        "channel": "google-listings-and-ads",
        "title": "22",
        "manage_url": "https://example.org/wp-admin/admin.php?page=wc-admin&path=/google/settings&subpath=/campaigns/edit",
        "cost": {
            "value": "200",
            "currency": "USD"
        }
    }
]

4. GET /wp-json/wc-admin/marketing/campaign-types

Returns an aggregated list of supported marketing campaign types for all registered marketing channels. Each marketing channel will provide this list by implementing the MarketingChannelInterface::get_supported_campaign_types method in their code base.

Example Response:

[
    {
        "id": "google-ads",
        "name": "Google Ads",
        "description": "Boost your product listings with a campaign that is automatically optimized to meet your goals.",
        "channel": {
            "slug": "google-listings-and-ads",
            "name": "Google Listings & Ads"
        },
        "create_url": "https://example.org/wp-admin/admin.php?page=wc-admin&path=/google/settings&subpath=/campaigns/create",
        "icon_url": "https://woocommerce.com/wp-content/uploads/2021/06/woo-GoogleListingsAds-jworee.png"
    }
]

Closes #34556.

How to test the changes in this Pull Request:

Before testing this PR, you must have at least one marketing channel installed and active on your store. Currently, we have only implemented the integration in the Google Listings & Ads extension (PR woocommerce/google-listings-and-ads#1730); therefore, to test this PR, you need to fetch the feature/mcm-integration branch of that extension and activate it on your store.

A. GET /wp-json/wc-admin/marketing/recommendations

  1. Make a request to this endpoint and confirm you receive an error indicating that the category parameter is required.
  2. Make another request with the category parameter set to channels and confirm only the marketing channel extensions are returned in the response. Marketing channels are extensions that have the sales-channel subcategory.
  3. Make another request with the category parameter set to extensions and confirm all other marketing extensions are returned in the response EXCEPT marketing channels.

B. GET /wp-json/wc-admin/marketing/channels

  1. Confirm that the Google Listings & Ads extension is active.
  2. Send a request to this endpoint and confirm that details about the GLA channel are returned in the response.
  3. Confirm that the values for is_setup_completed, errors_count, and product_listings_status are as they should be, depending on your setup.

C. GET /wp-json/wc-admin/marketing/campaigns

To test this endpoint, you must have at least one active marketing campaign defined in Google Listings & Ads. If not, we can mock some campaigns by modifying the GLAChannel.php file in Google Listings & Ads codebase and adding the following line right at the beginning of the GLAChannel::get_campaigns method:

return [
	new MarketingCampaign(
	'1',
	$this,
	'Test campaign',
	admin_url( 'admin.php?page=wc-admin&path=/google/settings&subpath=/campaigns/edit' ),
	new Price( '100', 'USD' ),
	),
];

This will return a marketing campaign when this endpoint is called.

  1. Confirm that the Google Listings & Ads extension is active and you have at least one active marketing campaign (or add the code above to return a mock campaign).
  2. Send a request to this endpoint and confirm that the campaign details are correct.

D. GET /wp-json/wc-admin/marketing/campaign-types

  1. Confirm that the Google Listings & Ads extension is active.
  2. Send a request to this endpoint and confirm that details about the Google Ads campaign type are returned in the response.
  3. Confirm that the create_url link works and points to the campaign create page of GLA.

Other information:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your changes, as applicable?
  • Have you created a changelog file for each project being changed, ie pnpm --filter=<project> changelog add?

FOR PR REVIEWER ONLY:

  • I have reviewed that everything is sanitized/escaped appropriately for any SQL or XSS injection possibilities. I made sure Linting is not ignored or disabled.

Nima added 18 commits December 14, 2022 14:33
Do not check if the marketing channel's slug exists in the list returned by WooCommerce.com Recommendation API. This essentially allows any third-party extension to register as a marketing channel.
The InstalledExtensions class will be used by the previous generation of Marketing dashboard (if the user has not enabled the new "Marketing" feature); therefore, it's best to restore it to the original code.
@nima-karimi nima-karimi added plugin: woocommerce Issues related to the WooCommerce Core plugin. focus: marketing Marketing page in WooCommerce Admin, i.e. `/wp-admin/admin.php?page=wc-admin&path=%2Fmarketing`. labels Dec 28, 2022
@nima-karimi nima-karimi requested a review from a team December 28, 2022 18:25
@nima-karimi nima-karimi self-assigned this Dec 28, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Dec 28, 2022

Test Results Summary

Commit SHA: c6ba33e

Test 🧪Passed ✅Failed 🚨Broken 🚧Skipped ⏭️Unknown ❔Total 📊Duration ⏱️
API Tests25900202610m 52s
E2E Tests189006019514m 37s

To view the full API test report, click here.
To view the full E2E test report, click here.
To view all test reports, visit the WooCommerce Test Reports Dashboard.

Nima added 2 commits January 3, 2023 14:55
This API returns the aggregated list of supported marketing campaign types for all registered marketing channels.
@nima-karimi
Copy link
Contributor Author

Update:

I've added another API to this PR to fetch the list of supported marketing campaign types (GET /wp-json/wc-admin/marketing/campaign-types).

Along with this API, a new method is added to the MarketingChannelInterface called get_supported_campaign_types. Each channel will implement this method in its code base and return an array of MarketingCampaignType objects. The MarketingCampaignType class represents a campaign type supported by each channel, such as Google Ads or Pinterest Ads.

Copy link
Contributor

@layoutd layoutd left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing went well except for a small issue in the tests, and one deprecation notice (due to using PHP 8.1 🔮):

GET wp-json/wc-admin/marketing/campaigns

<b>Deprecated</b>:  Return type of Automattic\WooCommerce\Admin\Marketing\Price: :jsonSerialize() should either be compatible with JsonSerializable: :jsonSerialize(): mixed, or the #[\ReturnTypeWillChange
] attribute should be used to temporarily suppress the notice in <b>/var/www/html/wp-content/plugins/woocommerce-monorepo/plugins/woocommerce/src/Admin/Marketing/Price.php</b> on line <b>64</b>

I also noticed the the campaign URLs returned for Google Listings & Ads are incorrect (commented in woocommerce/google-listings-and-ads#1730)

// Create a mock marketing campaign.
$test_campaign_1 = $this->createMock( MarketingCampaign::class );
$test_campaign_1->expects( $this->any() )->method( 'get_id' )->willReturn( 'test-campaign-1' );
$test_campaign_1->expects( $this->any() )->method( 'get_channel' )->willReturn( $test_channel_1 );
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MarketingCampaign::get_channel method doesn't exist anymore (8ef6532). Looks like it would need to be changed to get_type, which would have to return a mocked MarketingCampaignType.

This doesn't seem to affect the assertions in this test, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops missed that one! Fixed in c6ba33e

@nima-karimi
Copy link
Contributor Author

Thanks for the review Justin. I removed the jsonSerialize from the Price class since it wasn't being used and now the php8.1 deprecation notice should be gone. The issue with GLA integration is also fixed in its PR.

@nima-karimi nima-karimi merged commit b2ff0ba into feature/34548-multichannel-marketing-backend Jan 13, 2023
@nima-karimi nima-karimi deleted the feature/34556-marketing-api branch January 13, 2023 16:54
nima-karimi added a commit that referenced this pull request Jan 20, 2023
* Multichannel Marketing - Core Library (#35099)

* Create channel interface and campaign value class

* Create MarketingChannels class

* Register MarketingChannels class in DI container

* Use the new MarketingChannels class to get the installed marketing extensions' data

* Use DI container to access InstalledExtensions class

* Add InstalledExtensions to the $provides array

* Hint that campaign cost should also indicate the currency

* Initialize the channels array

* Add unit tests for MarketingCampaign

* Add unit tests for MarketingChannels

* Add Price class to represent a price with currency

* Use Price class for marketing campaign's cost

* Define a constant to indicate the MCM classes exist

This constant will be checked by third-party extensions before utilizing any of the classes/interfaces defined for this feature.

* Create MarketingSpecs class to include WC.com API calls

* Remove WC.com API calls from Marketing class

And replace them with calls from MarketingSpecs class.

* Use the const from MarketingSpecs

* Fix MarketingChannels unit tests

* Add missing settings URL to the channel data

Co-authored-by: Nima <nima.karimi@automattic.com>

* Multichannel Marketing - Changes to the marketing classes (#36012)

* Rename `get_errors_no` to `get_errors_count`

* Remove the validation for marketing channel slugs

Do not check if the marketing channel's slug exists in the list returned by WooCommerce.com Recommendation API. This allows any third-party extension to register as a marketing channel.

* Revert InstalledExtensions

The InstalledExtensions class will be used by the previous generation of the Marketing dashboard (if the user has not enabled the new "Marketing" feature); therefore, it's best to restore it to the original code.

* Fix code style

* Translate Exception message

* Remove doc references to a predetermined list of marketing channels

Co-authored-by: Nima <nima.karimi@automattic.com>

* Multichannel Marketing - API (#36222)

* Rename `get_errors_no` to `get_errors_count`

* Remove the validation for marketing channel slugs

Do not check if the marketing channel's slug exists in the list returned by WooCommerce.com Recommendation API. This essentially allows any third-party extension to register as a marketing channel.

* Revert InstalledExtensions

The InstalledExtensions class will be used by the previous generation of Marketing dashboard (if the user has not enabled the new "Marketing" feature); therefore, it's best to restore it to the original code.

* Fix code style

* Add channel property to MarketingCampaign

* Add methods to filter the recommended marketing channels and extensions

* Add `marketing/recommendations` API

* Add unit tests for `marketing/recommendations` API

* Add `marketing/channels` API

* Add unit tests for `marketing/channels` API

* Add `marketing/campaigns` API

* Add unit tests for `marketing/campaigns` API

* Translate Exception message

* Remove doc references to predetermined list of marketing channels

* Add `unregister_all` method

To allow unregistering all marketing channels.

* Unregister all channels on test tear down

* Change API access denied authorization code

* Change API access permission

* Add MarketingCampaignType class

This allows defining campaign types for each marketing channel.

* Add campaign type property to campaign class

* Add `marketing/campaign-types` API

This API returns the aggregated list of supported marketing campaign types for all registered marketing channels.

* Add unit tests for `marketing/campaign-types` API

* Remove unused jsonSerialize method

* Fix unit tests

Co-authored-by: Nima <nima.karimi@automattic.com>

* Add changelog

* Add product listing status sync failed

Co-authored-by: Nima <nima.karimi@automattic.com>
vedanshujain pushed a commit that referenced this pull request Jan 25, 2023
* Multichannel Marketing - Core Library (#35099)

* Create channel interface and campaign value class

* Create MarketingChannels class

* Register MarketingChannels class in DI container

* Use the new MarketingChannels class to get the installed marketing extensions' data

* Use DI container to access InstalledExtensions class

* Add InstalledExtensions to the $provides array

* Hint that campaign cost should also indicate the currency

* Initialize the channels array

* Add unit tests for MarketingCampaign

* Add unit tests for MarketingChannels

* Add Price class to represent a price with currency

* Use Price class for marketing campaign's cost

* Define a constant to indicate the MCM classes exist

This constant will be checked by third-party extensions before utilizing any of the classes/interfaces defined for this feature.

* Create MarketingSpecs class to include WC.com API calls

* Remove WC.com API calls from Marketing class

And replace them with calls from MarketingSpecs class.

* Use the const from MarketingSpecs

* Fix MarketingChannels unit tests

* Add missing settings URL to the channel data

Co-authored-by: Nima <nima.karimi@automattic.com>

* Multichannel Marketing - Changes to the marketing classes (#36012)

* Rename `get_errors_no` to `get_errors_count`

* Remove the validation for marketing channel slugs

Do not check if the marketing channel's slug exists in the list returned by WooCommerce.com Recommendation API. This allows any third-party extension to register as a marketing channel.

* Revert InstalledExtensions

The InstalledExtensions class will be used by the previous generation of the Marketing dashboard (if the user has not enabled the new "Marketing" feature); therefore, it's best to restore it to the original code.

* Fix code style

* Translate Exception message

* Remove doc references to a predetermined list of marketing channels

Co-authored-by: Nima <nima.karimi@automattic.com>

* Multichannel Marketing - API (#36222)

* Rename `get_errors_no` to `get_errors_count`

* Remove the validation for marketing channel slugs

Do not check if the marketing channel's slug exists in the list returned by WooCommerce.com Recommendation API. This essentially allows any third-party extension to register as a marketing channel.

* Revert InstalledExtensions

The InstalledExtensions class will be used by the previous generation of Marketing dashboard (if the user has not enabled the new "Marketing" feature); therefore, it's best to restore it to the original code.

* Fix code style

* Add channel property to MarketingCampaign

* Add methods to filter the recommended marketing channels and extensions

* Add `marketing/recommendations` API

* Add unit tests for `marketing/recommendations` API

* Add `marketing/channels` API

* Add unit tests for `marketing/channels` API

* Add `marketing/campaigns` API

* Add unit tests for `marketing/campaigns` API

* Translate Exception message

* Remove doc references to predetermined list of marketing channels

* Add `unregister_all` method

To allow unregistering all marketing channels.

* Unregister all channels on test tear down

* Change API access denied authorization code

* Change API access permission

* Add MarketingCampaignType class

This allows defining campaign types for each marketing channel.

* Add campaign type property to campaign class

* Add `marketing/campaign-types` API

This API returns the aggregated list of supported marketing campaign types for all registered marketing channels.

* Add unit tests for `marketing/campaign-types` API

* Remove unused jsonSerialize method

* Fix unit tests

Co-authored-by: Nima <nima.karimi@automattic.com>

* Add changelog

* Add product listing status sync failed

Co-authored-by: Nima <nima.karimi@automattic.com>
@ecgan
Copy link
Member

ecgan commented Feb 1, 2023

3. GET /wp-json/wc-admin/marketing/campaigns

@nima-karimi , I noticed that the campaigns API response data does not have a "summary description" for the campaigns.

The following screenshot is the figma design for your reference, where we have short, dynamic descriptions for different campaigns:

image

I suppose this can be done in future iterations.

@ecgan
Copy link
Member

ecgan commented Feb 1, 2023

3. GET /wp-json/wc-admin/marketing/campaigns

[...] This API returns a paginated response and accepts the following two parameters:

  • page
  • per_page

Example Response:

@nima-karimi , we need to have a "total number of rows" or "total number of pages" in the API response so that we can display total number of pages (i.e. "Page 1 of 2") in the pagination UI.

image

For now, I will code in a large enough per_page value to get "all" the campaigns in one request.

@nima-karimi
Copy link
Contributor Author

@ecgan

we need to have a "total number of rows" or "total number of pages" in the API response so that we can display total number of pages (i.e. "Page 1 of 2") in the pagination UI.

Oh, sorry should've mentioned this in the descriptions, but the following HTTP response headers already provide this info:

  • X-WP-Total - The total number of campaigns
  • X-WP-TotalPages - Total number of pages

Other WooCommerce endpoints are also using these headers to render this information, but let me know if it'd be easier to have these in the JSON response.

@ecgan
Copy link
Member

ecgan commented Feb 3, 2023

the following HTTP response headers already provide this info:

  • X-WP-Total - The total number of campaigns
  • X-WP-TotalPages - Total number of pages

@nima-karimi , I thought I looked into the response headers too but I guess I missed it 😂 Thanks for the info, I'll use that then. 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
focus: marketing Marketing page in WooCommerce Admin, i.e. `/wp-admin/admin.php?page=wc-admin&path=%2Fmarketing`. plugin: woocommerce Issues related to the WooCommerce Core plugin.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants