Skip to content

Commit

Permalink
Added Order paid completed webhook
Browse files Browse the repository at this point in the history
  • Loading branch information
plance committed Nov 25, 2024
1 parent 8d0194d commit 36f0d52
Show file tree
Hide file tree
Showing 10 changed files with 205 additions and 60 deletions.
5 changes: 4 additions & 1 deletion README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Contributors: gtmserver,bukashk0zzz
Tags: google tag manager, google tag manager server side, gtm, gtm server side, tag manager, tagmanager, analytics, google, serverside, server-side, gtag
Requires at least: 5.2.0
Tested up to: 6.7.0
Stable tag: 2.1.23
Stable tag: 2.1.24
License: GPLv2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html

Expand Down Expand Up @@ -67,6 +67,9 @@ Yes. <a href="https://stape.io/blog/how-to-set-up-facebook-conversion-api">How t

== Changelog ==

= 2.1.24 =
* Added Order paid completed webhook

= 2.1.23 =
* Fix purchase event

Expand Down
7 changes: 4 additions & 3 deletions assets/js/admin-javascript.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,13 @@ jQuery( document ).ready(
}

var isPurchaseChecked = jQuery( '#gtm_server_side_webhooks_purchase' ).is( ':checked' );
var isRefundChecked = jQuery( '#gtm_server_side_webhooks_refund' ).is( ':checked' );
var isProcessingChecked = jQuery( '#gtm_server_side_webhooks_processing' ).is( ':checked' );
var isCompletedChecked = jQuery( '#gtm_server_side_webhooks_completed' ).is( ':checked' );
var isRefundChecked = jQuery( '#gtm_server_side_webhooks_refund' ).is( ':checked' );

return isPurchaseChecked || isRefundChecked || isProcessingChecked;
return isPurchaseChecked || isProcessingChecked || isCompletedChecked || isRefundChecked;
},
'Select purchase and/or refund webhook'
'Select one or more webhooks'
);

// Tab "General".
Expand Down
1 change: 1 addition & 0 deletions bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
define( 'GTM_SERVER_SIDE_FIELD_WEBHOOKS_CONTAINER_URL', 'gtm_server_side_webhooks_container_url' );
define( 'GTM_SERVER_SIDE_FIELD_WEBHOOKS_PURCHASE', 'gtm_server_side_webhooks_purchase' );
define( 'GTM_SERVER_SIDE_FIELD_WEBHOOKS_PROCESSING', 'gtm_server_side_webhooks_processing' );
define( 'GTM_SERVER_SIDE_FIELD_WEBHOOKS_COMPLETED', 'gtm_server_side_webhooks_completed' );
define( 'GTM_SERVER_SIDE_FIELD_WEBHOOKS_REFUND', 'gtm_server_side_webhooks_refund' );

define( 'GTM_SERVER_SIDE_FIELD_PLACEMENT_VALUE_CODE', 'code' );
Expand Down
3 changes: 2 additions & 1 deletion gtm-server-side.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
* Plugin Name: GTM Server Side
* Plugin URI: https://wordpress.org/plugins/gtm-server-side/
* Description: Enhance conversion tracking by implementing server-side tagging using server Google Tag Manager container. Effortlessly configure data layer events in web GTM, send webhooks, set up custom loader, and extend cookie lifetime.
* Version: 2.1.23
* Version: 2.1.24
* Author: Stape
* Author URI: https://stape.io
* License: GPL-2.0+
Expand All @@ -32,6 +32,7 @@
add_action( 'gtm_server_side', array( GTM_Server_Side_I18n::class, 'instance' ) );
add_action( 'gtm_server_side', array( GTM_Server_Side_Webhook_Purchase::class, 'instance' ) );
add_action( 'gtm_server_side', array( GTM_Server_Side_Webhook_Processing::class, 'instance' ) );
add_action( 'gtm_server_side', array( GTM_Server_Side_Webhook_Completed::class, 'instance' ) );
add_action( 'gtm_server_side', array( GTM_Server_Side_Webhook_Refund::class, 'instance' ) );
add_action( 'gtm_server_side_admin', array( GTM_Server_Side_Admin_Settings::class, 'instance' ) );
add_action( 'gtm_server_side_admin', array( GTM_Server_Side_Admin_Ajax::class, 'instance' ) );
Expand Down
123 changes: 72 additions & 51 deletions includes/class-gtm-server-side-admin-ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,19 @@ public function gtm_server_side_webhook_test() {
);
}

$is_refund = GTM_Server_Side_Helpers::get_option( GTM_SERVER_SIDE_FIELD_WEBHOOKS_REFUND );
$is_purchase = GTM_Server_Side_Helpers::get_option( GTM_SERVER_SIDE_FIELD_WEBHOOKS_PURCHASE );
$is_processing = GTM_Server_Side_Helpers::get_option( GTM_SERVER_SIDE_FIELD_WEBHOOKS_PROCESSING );
if ( empty( $is_purchase ) && empty( $is_refund ) && empty( $is_processing ) ) {
$is_completed = GTM_Server_Side_Helpers::get_option( GTM_SERVER_SIDE_FIELD_WEBHOOKS_COMPLETED );
$is_refund = GTM_Server_Side_Helpers::get_option( GTM_SERVER_SIDE_FIELD_WEBHOOKS_REFUND );
if (
empty( $is_purchase ) &&
empty( $is_processing ) &&
empty( $is_completed ) &&
empty( $is_refund )
) {
wp_send_json_error(
array(
'message' => __( 'Purchase or order paid or refund webhook is required.', 'gtm-server-side' ),
'message' => __( 'Purchase or order paid processing or order paid completed or refund webhook is required.', 'gtm-server-side' ),
)
);
}
Expand All @@ -74,6 +80,10 @@ public function gtm_server_side_webhook_test() {
$answer[] = $this->send_webhook_processing();
}

if ( ! empty( $is_completed ) ) {
$answer[] = $this->send_webhook_completed();
}

if ( ! empty( $is_refund ) ) {
$answer[] = $this->send_webhook_refund();
}
Expand Down Expand Up @@ -102,28 +112,7 @@ public function gtm_server_side_webhook_test() {
private function send_webhook_purchase() {
$request = array(
'event' => 'purchase',
'ecommerce' => array(
'transaction_id' => '358',
'affiliation' => 'test',
'value' => 18.00,
'tax' => 0,
'shipping' => 0,
'currency' => 'USD',
'coupon' => 'test_coupon',
'items' => array(
array(
'item_name' => 'Beanie',
'item_brand' => 'Stape',
'item_id' => '15',
'item_sku' => 'woo-beanie',
'price' => 18.00,
'item_category' => 'Clothing',
'item_category2' => 'Accessories',
'quantity' => 1,
'index' => 1,
),
),
),
'ecommerce' => $this->get_ecommerce_data(),
);

$result = $this->send_request( $request );
Expand All @@ -139,47 +128,49 @@ private function send_webhook_purchase() {
}

/**
* Send webhooks processing (order paid).
* Send webhooks processing (order paid processing).
*
* @return string
*/
private function send_webhook_processing() {
$request = array(
'event' => 'order_paid',
'ecommerce' => array(
'transaction_id' => '358',
'affiliation' => 'test',
'value' => 18.00,
'tax' => 0,
'shipping' => 0,
'currency' => 'USD',
'coupon' => 'test_coupon',
'items' => array(
array(
'item_name' => 'Beanie',
'item_brand' => 'Stape',
'item_id' => '15',
'item_sku' => 'woo-beanie',
'price' => 18.00,
'item_category' => 'Clothing',
'item_category2' => 'Accessories',
'quantity' => 1,
'index' => 1,
),
),
),
'ecommerce' => $this->get_ecommerce_data(),
);

$result = $this->send_request( $request );
if ( is_wp_error( $result ) ) {
wp_send_json_error(
array(
'message' => __( 'Some problem with Purchase webhook.', 'gtm-server-side' ),
'message' => __( 'Some problem with order paid processing webhook.', 'gtm-server-side' ),
)
);
}

return __( 'Order paid processing webhook sent.', 'gtm-server-side' );
}

/**
* Send webhooks completed (order paid completed).
*
* @return string
*/
private function send_webhook_completed() {
$request = array(
'event' => 'order_completed',
'ecommerce' => $this->get_ecommerce_data(),
);

$result = $this->send_request( $request );
if ( is_wp_error( $result ) ) {
wp_send_json_error(
array(
'message' => __( 'Some problem with order paid completed webhook.', 'gtm-server-side' ),
)
);
}

return __( 'Order paid webhook sent.', 'gtm-server-side' );
return __( 'Order paid completed webhook sent.', 'gtm-server-side' );
}

/**
Expand Down Expand Up @@ -244,7 +235,7 @@ private function send_request( $body ) {
}

/**
* Return user request test data
* Return user request test data.
*
* @return array
*/
Expand Down Expand Up @@ -275,4 +266,34 @@ private function get_request_user_data() {
'new_customer' => 'false',
);
}

/**
* Return ecommerce test data.
*
* @return array
*/
private function get_ecommerce_data() {
return array(
'transaction_id' => '358',
'affiliation' => 'test',
'value' => 18.00,
'tax' => 0,
'shipping' => 0,
'currency' => 'USD',
'coupon' => 'test_coupon',
'items' => array(
array(
'item_name' => 'Beanie',
'item_brand' => 'Stape',
'item_id' => '15',
'item_sku' => 'woo-beanie',
'price' => 18.00,
'item_category' => 'Clothing',
'item_category2' => 'Accessories',
'quantity' => 1,
'index' => 1,
),
),
);
}
}
28 changes: 26 additions & 2 deletions includes/class-gtm-server-side-admin-settings.php
Original file line number Diff line number Diff line change
Expand Up @@ -441,7 +441,7 @@ function() {
);
add_settings_field(
GTM_SERVER_SIDE_FIELD_WEBHOOKS_PROCESSING,
__( 'Order paid webhook', 'gtm-server-side' ),
__( 'Order paid webhook - processing', 'gtm-server-side' ),
function() {
echo '<input
type="checkbox"
Expand All @@ -450,7 +450,31 @@ function() {
' . checked( GTM_Server_Side_Helpers::get_option( GTM_SERVER_SIDE_FIELD_WEBHOOKS_PROCESSING ), 'yes', false ) . '
value="yes">';
echo '<br>';
printf( __( 'Order paid event will be sent whenever an order is paid (has "Processing" status as per <a href="%s" target="_blank">Woocommerce documentation</a>).', 'gtm-server-side' ), 'https://woocommerce.com/document/managing-orders/order-statuses/' ); // phpcs:ignore
printf( __( 'order_paid event will be sent whenever an order is paid (has "Processing" status as per <a href="%s" target="_blank">Woocommerce documentation</a>).', 'gtm-server-side' ), 'https://woocommerce.com/document/managing-orders/order-statuses/' ); // phpcs:ignore
},
GTM_SERVER_SIDE_ADMIN_SLUG,
GTM_SERVER_SIDE_ADMIN_GROUP_WEBHOOKS
);

register_setting(
GTM_SERVER_SIDE_ADMIN_GROUP,
GTM_SERVER_SIDE_FIELD_WEBHOOKS_COMPLETED,
array(
'sanitize_callback' => 'GTM_Server_Side_Helpers::sanitize_bool',
)
);
add_settings_field(
GTM_SERVER_SIDE_FIELD_WEBHOOKS_COMPLETED,
__( 'Order paid webhook - completed', 'gtm-server-side' ),
function() {
echo '<input
type="checkbox"
id="' . esc_attr( GTM_SERVER_SIDE_FIELD_WEBHOOKS_COMPLETED ) . '"
name="' . esc_attr( GTM_SERVER_SIDE_FIELD_WEBHOOKS_COMPLETED ) . '"
' . checked( GTM_Server_Side_Helpers::get_option( GTM_SERVER_SIDE_FIELD_WEBHOOKS_COMPLETED ), 'yes', false ) . '
value="yes">';
echo '<br>';
printf( __( 'order_completed event will be sent whenever order status becomes completed (has "Completed" status as per <a href="%s" target="_blank">Woocommerce documentation</a>).', 'gtm-server-side' ), 'https://woocommerce.com/document/managing-orders/order-statuses/' ); // phpcs:ignore
},
GTM_SERVER_SIDE_ADMIN_SLUG,
GTM_SERVER_SIDE_ADMIN_GROUP_WEBHOOKS
Expand Down
8 changes: 8 additions & 0 deletions includes/class-gtm-server-side-wc-helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,10 @@ public function get_order_data_layer_items( $items ) {
foreach ( $items as $item_loop ) {
$product = $item_loop->get_product();

if ( ! ( $product instanceof WC_Product ) ) {
continue;
}

$array = $this->get_data_layer_item( $product );
$array['quantity'] = intval( $item_loop->get_quantity() );
$array['index'] = $index++;
Expand All @@ -118,6 +122,10 @@ public function get_cart_data_layer_items( $cart ) {
foreach ( $cart as $product_loop ) {
$product = $product_loop['data'];

if ( ! ( $product instanceof WC_Product ) ) {
continue;
}

$array = $this->get_data_layer_item( $product );
$array['quantity'] = intval( $product_loop['quantity'] );
$array['index'] = $index++;
Expand Down
86 changes: 86 additions & 0 deletions includes/class-gtm-server-side-webhook-completed.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<?php
/**
* Webhook Completed.
*
* @package GTM_Server_Side
* @subpackage GTM_Server_Side/includes
* @since 2.0.0
*/

defined( 'ABSPATH' ) || exit;

/**
* Webhook Completed.
*/
class GTM_Server_Side_Webhook_Completed {
use GTM_Server_Side_Singleton;

/**
* Init.
*
* @return void
*/
public function init() {
if ( ! function_exists( 'WC' ) ) {
return;
}

add_action( 'woocommerce_order_status_completed', array( $this, 'woocommerce_order_status_completed' ) );
}

/**
* Order change status to completed.
*
* @param int $order_id Order id.
* @return void
*/
public function woocommerce_order_status_completed( $order_id ) {
if ( ! GTM_Server_Side_Helpers::is_enable_webhook() ) {
return;
}

if ( GTM_SERVER_SIDE_FIELD_VALUE_YES !== GTM_Server_Side_Helpers::get_option( GTM_SERVER_SIDE_FIELD_WEBHOOKS_COMPLETED ) ) {
return;
}

$order = wc_get_order( $order_id );
if ( ! ( $order instanceof WC_Order ) ) {
return;
}

$request = array(
'event' => 'order_completed',
'ecommerce' => array(
'transaction_id' => esc_attr( $order->get_order_number() ),
'affiliation' => '',
'value' => GTM_Server_Side_WC_Helpers::instance()->formatted_price( $order->get_total() ),
'tax' => GTM_Server_Side_WC_Helpers::instance()->formatted_price( $order->get_total_tax() ),
'shipping' => GTM_Server_Side_WC_Helpers::instance()->formatted_price( $order->get_shipping_total() ),
'currency' => esc_attr( $order->get_currency() ),
'coupon' => esc_attr( join( ',', $order->get_coupon_codes() ) ),
'items' => GTM_Server_Side_WC_Helpers::instance()->get_order_data_layer_items( $order->get_items() ),
),
'user_data' => GTM_Server_Side_WC_Helpers::instance()->get_order_user_data( $order ),
);

$request_cookies = GTM_Server_Side_Helpers::get_request_cookies();

if ( ! empty( $request_cookies ) ) {
$request['cookies'] = $request_cookies;

if ( isset( $request_cookies['_dcid'] ) ) {
$request['client_id'] = $request_cookies['_dcid'];
}
}

/**
* Allows modification of processing order webhook payload.
*
* @param array $request Webhook payload data.
* @param object $order WC_Order instance.
*/
$request = apply_filters( 'gtm_server_side_processing_webhook_payload', $request, $order );

GTM_Server_Side_Helpers::send_webhook_request( $request );
}
}
Loading

0 comments on commit 36f0d52

Please sign in to comment.