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

Pinterest Conversions API #787

Merged
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
5cab33b
Add Pinterest Conversions API integration.
message-dimke Jun 30, 2023
fa1fb3c
Update Pinterest conversions code with a new code structure.
message-dimke Jun 30, 2023
298c3a1
Fix php code styling for event id provider.
message-dimke Jun 30, 2023
259d920
Update even data with required values. Add minor php code styling cha…
message-dimke Jun 30, 2023
9fe26da
Intermediate code commit. Refactor tracking into separate pinterest t…
message-dimke Aug 3, 2023
620bb7d
Remove API conversion files. Add event id to data objects. Refactor c…
message-dimke Aug 4, 2023
333c490
Remove not needed JS search form event listener.
message-dimke Aug 4, 2023
5fcb37c
Add tracking test.
message-dimke Aug 5, 2023
8f1e71d
Add more tacking tests.
message-dimke Aug 5, 2023
1bba76f
Remove classes we do not need and add Tag class Unit tests.
message-dimke Aug 5, 2023
9623fa1
Update doc blocks.
message-dimke Aug 5, 2023
47a9b4d
Add missing doc comments. Remove unused Event class.
message-dimke Aug 7, 2023
cada25b
Fix doc errors. Add Conversions API request logging.
message-dimke Aug 7, 2023
f623693
Add a note to the call.
message-dimke Aug 8, 2023
0592e85
Change action to hook into with checkout event.
message-dimke Aug 8, 2023
7f39ed0
Apply suggestions from code review
message-dimke Aug 15, 2023
c773bd2
Adding conversions unit tests. Tiny refactoring of tracking class.
message-dimke Aug 14, 2023
fbdb648
Refactoring conversions event data preparation into methods.
message-dimke Aug 15, 2023
e28965b
Refactor trackers into tracking class parameters.
message-dimke Aug 15, 2023
a950452
Refactor tracker request data preparation.
message-dimke Aug 15, 2023
6ddd211
Conversions request data preparation refactoring. Tweak phpdoc commen…
message-dimke Aug 16, 2023
03a4401
Refactor event type map. Refactor request data preparation functions.
message-dimke Aug 17, 2023
d6a9fcd
Fix phpcs errors on parameter comments missing.
message-dimke Aug 17, 2023
747c901
Refactor conversions api request/response exception handling.
message-dimke Aug 17, 2023
6d41c44
Remove forbidden ternaries.
message-dimke Aug 17, 2023
fe62641
Fix php doc error.
message-dimke Aug 17, 2023
cb1f198
Fix php doc error.
message-dimke Aug 17, 2023
e059caf
Adjust unit test to reflect the recent changes in response handling.
message-dimke Aug 17, 2023
6d945cd
Adding JS event on ajax add to cart button.
message-dimke Aug 23, 2023
78d5627
Adding check is cart fragments are enabled and if not - enqueue the e…
message-dimke Aug 23, 2023
1c5ca5e
Merge branch 'pinterest-v5-integration-branch' into add/pinterest-con…
message-dimke Aug 29, 2023
301792c
Remove unused unit test for tracking class. Optimise imports for feed…
message-dimke Aug 29, 2023
12d20e4
Update connection URL endpoint name.
budzanowski Aug 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 118 additions & 0 deletions src/API/Conversions.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
<?php
/**
* @package Pinterest_For_Woocommerce/API
*/
namespace Automattic\WooCommerce\Pinterest\API;

use Automattic\WooCommerce\Pinterest\API\Conversions\CartData;
use Automattic\WooCommerce\Pinterest\API\Conversions\CustomData;
use Automattic\WooCommerce\Pinterest\API\Conversions\PinterestConversionsEventIdProvider;
use Automattic\WooCommerce\Pinterest\API\Conversions\SearchData;
use Automattic\WooCommerce\Pinterest\API\Conversions\UserData;
use Exception;

class Conversions {

private UserData $user_data;

/**
* @var CartData|SearchData $custom_data
*/
private CustomData $custom_data;

public function __construct( UserData $user_data, CustomData $custom_data ) {
$this->user_data = $user_data;
$this->custom_data = $custom_data;
}

/**
* An array of event names to event IDs map for the Pinterest Conversions API and Pinterest Tag.
*
* @since x.x.x
*
* @param string $event_name
* @param array $data
*/
public function add_event( string $event_name, array $data = array() ) {
$ad_account_id = Pinterest_For_WooCommerce()::get_setting( 'tracking_advertiser' );

$data = array_merge(
$data,
array(
'ad_account_id' => $ad_account_id,
'event_name' => $event_name,
'action_source' => 'website',
'event_time' => time(),
'user_data' => array(
'client_ip_address' => $this->user_data->get_client_ip_address(),
'client_user_agent' => $this->user_data->get_client_user_agent(),
),
'event_id' => PinterestConversionsEventIdProvider::get_event_id( $event_name ),
'event_source_url' => '',
)
);

$conversions_event_name = PinterestConversionsEventIdProvider::get_event_name_by_pinterest_tag_event_name( $event );
if ( in_array( $conversions_event_name, array( 'add_to_cart', 'checkout', 'purchase' ), true ) ) {
$data = $this->add_cart_and_checkout_custom_data( $data );
}

if ( in_array( $conversions_event_name, array( 'search', 'view_search_results' ), true ) ) {
$data = $this->add_search_custom_data( $data );
}

try {
APIV5::make_request(
"ad_accounts/{$ad_account_id}/events",
'POST',
$data
);
} catch ( Exception $e ) {
// Do nothing.
}
}

/**
* Adds custom data related to add to cart and checkout events.
*
* @since x.x.x
* @link https://developers.pinterest.com/docs/conversions/best/#Required#Custom%20data%20object
*
* @param array $event_data
* @return array|string[][]
*/
private function add_cart_and_checkout_custom_data( array $event_data ): array {
return array_merge(
$event_data,
array(
'custom_data' => array(
'currency' => $this->custom_data->get_currency(),
'value' => $this->custom_data->get_value(),
'content_ids' => $this->custom_data->get_content_ids(),
'contents' => $this->custom_data->get_contents(),
'num_items' => $this->custom_data->get_num_items(),
'order_id' => $this->custom_data->get_order_id(),
),
)
);
}

/**
* Adds custom data related to search events.
*
* @since x.x.x
*
* @param array $event_data
* @return array
*/
private function add_search_custom_data( array $event_data ): array {
return array_merge(
$event_data,
array(
'custom_data' => array(
'search_string' => $this->custom_data->get_search_string(),
),
)
);
}
}
100 changes: 100 additions & 0 deletions src/API/Conversions/CartData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
<?php
/**
* @package Pinterest_For_Woocommerce/API/Conversions
*/
namespace Automattic\WooCommerce\Pinterest\API\Conversions;

/**
* Custom data for events which require cart data e.g. add to cart, checkout, purchase, etc.
*
* @link https://developers.pinterest.com/docs/conversions/best/#Required,%20recommended,%20and%20optional%20fields
*
* @since x.x.x
*/
class CartData implements CustomData {

/**
* @var string ISO-4217 currency code.
*/
private string $currency;

/**
* @var string A total value of the event. E.g. if there are multiple items in a checkout event, value should be \
* the total price of all items. Accepted as a string, parsed into a double. Strongly recommended for \
* add-to-cart or checkout events.
*/
private string $value;

/**
* @var string[] Product IDs as an array of strings. Strongly recommended for page_visit, add-to-cart and \
* checkout events.
*/
private array $content_ids;

/**
* @var array An array of objects, each containing item price and quantity for an individual product. \
* Strongly recommended for add-to-cart or checkout events.
*/
private array $contents;

/**
* @var int Total number of products in the event. Strongly recommended for add-to-cart or checkout events.
*/
private int $num_items;

/**
* @var string A unique ID representing the order. Strongly recommended for add-to-cart or checkout events.
*/
private string $order_id;

public function __construct( string $currency, string $value, array $content_ids, array $contents, int $num_items, string $order_id ) {
$this->currency = $currency;
$this->value = $value;
$this->content_ids = $content_ids;
$this->contents = $contents;
$this->num_items = $num_items;
$this->order_id = $order_id;
}

/**
* @return string
*/
public function get_currency(): string {
return $this->currency;
}

/**
* @return string
*/
public function get_value(): string {
return $this->value;
}

/**
* @return array
*/
public function get_content_ids(): array {
return $this->content_ids;
}

/**
* @return array
*/
public function get_contents(): array {
return $this->contents;
}

/**
* @return int
*/
public function get_num_items(): int {
return $this->num_items;
}

/**
* @return string
*/
public function get_order_id(): string {
return $this->order_id;
}
}
14 changes: 14 additions & 0 deletions src/API/Conversions/CustomData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
/**
* @package Pinterest_For_Woocommerce/API/Conversions
*/
namespace Automattic\WooCommerce\Pinterest\API\Conversions;

/**
* A common interface for custom data classes.
*
* @link https://developers.pinterest.com/docs/conversions/best/#Required,%20recommended,%20and%20optional%20fields
*
* @since x.x.x
*/
interface CustomData {}
12 changes: 12 additions & 0 deletions src/API/Conversions/NoData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php
/**
* @package Pinterest_For_Woocommerce/API/Conversions
*/
namespace Automattic\WooCommerce\Pinterest\API\Conversions;

/**
* Used as a stub when no custom data is needed.
*
* @since x.x.x
*/
class NoData implements CustomData {}
85 changes: 85 additions & 0 deletions src/API/Conversions/PinterestConversionsEventIdProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
<?php
/**
* Pinterest Tag and Conversion API event ID provider.
*
* @since x.x.x
* @package Pinterest_For_Woocommerce/API/Conversions
*/

namespace Automattic\WooCommerce\Pinterest\API\Conversions;

/**
* @since x.x.x
*/
class PinterestConversionsEventIdProvider {

/**
* An array of event names to event IDs map for the Pinterest Conversions API and Pinterest Tag.
*
* @since x.x.x
*
* @var string[]
*/
private static $event_ids = [];

/**
* Pinterest Tag and Pinterest API for Conversions have different event names.
* Since Pinterest Tag was here first we use its event names as the keys.
*
* @since x.x.x
*
* @var array|string[] An array of event names to Pinterest Tag API names map.
*/
private static $tag_api_name_map = [
'pagevisit' => 'page_view',
'addtocart' => 'add_to_cart',
'checkout' => 'checkout',
'lead' => 'lead',
'purchase' => 'purchase',
'search' => 'search',
'viewcategory' => 'view_category',
'viewitem' => 'view_item',
'viewsearchresults' => 'view_search_results',
];

/**
* Returns a persisted event ID for the given event name.
*
* @since x.x.x
*
* @param string $event_name
* @return string
*/
public static function get_event_id( string $event_name ): string {
$event_name = static::$tag_api_name_map[ strtolower( $event_name ) ] ?? $event_name;
return static::$event_ids[ $event_name ] ?? static::generate_event_id( $event_name );
}

/**
* Generates a new event ID for the given event name and stores is in-memory.
*
* @since x.x.x
*
* @param string $event_name
* @return string
*/
private static function generate_event_id( string $event_name ): string {
$id = uniqid( 'pinterest-for-woocommerce-conversions-event-id-for-' . $event_name );

static::$event_ids[ $event_name ] = $id;

return $id;
}

/**
* Returns the Pinterest Conversions API event name for the given Pinterest Tag API event name.
*
* @since x.x.x
*
* @param string $pinterest_tag_event_name
* @return string
*/
public static function get_event_name_by_pinterest_tag_event_name( string $pinterest_tag_event_name ): string {
return static::$tag_api_name_map[ strtolower( $pinterest_tag_event_name ) ] ?? $pinterest_tag_event_name;
}
}
31 changes: 31 additions & 0 deletions src/API/Conversions/SearchData.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php
/**
* @package Pinterest_For_Woocommerce/API/Conversions
*/
namespace Automattic\WooCommerce\Pinterest\API\Conversions;

/**
* Custom data for events which require search string e.g. search, view search results, etc.
*
* @link https://developers.pinterest.com/docs/conversions/best/#Required,%20recommended,%20and%20optional%20fields
*
* @since x.x.x
*/
class SearchData implements CustomData {

/**
* @var string A search string related to the conversion event.
*/
private string $search_string;

public function __construct(string $search_string ) {
$this->search_string = $search_string;
}

/**
* @return string
*/
public function get_search_string(): string {
return $this->search_string;
}
}
Loading