Creating duplicate edd purchase events
-
Currently seeing multiple hits to the pixel purchase event if users refresh the purchase receipt page.
I know other plugins have an option to prevent this. Can I get some tips on how I might do that in your plugin? (I have purchased the other plugin, but even still prefer yours).
-
This topic was modified 6 years, 12 months ago by
Daniel Iser.
-
This topic was modified 6 years, 12 months ago by
-
Also while looking at EDD events, the AddToCart event has the proper content_type, content_ids & value, but the
content_name
shows asNot Set
rather than the product name.Hi,
unfortunately, there isn’t an easy way to prevent multiple purchase hits, but I like the feature and I’ll try to include the fix for this in next releases of the plugin. For now, if you want to avoid this, I could suggest this code to add in the
functions.php
file of the active theme, or in a new plugin:add_filter('aepc_can_track', function($can, $event) { if ( ! in_array( $event, array( 'purchase' ) ) || ! $can ) { return $can; } global $wp, $edd_receipt_args; // Get the Order ID if ( ! empty( $wp->query_vars['order-received'] ) ) { $plugin = 'wc'; $order_id = intval( $wp->query_vars['order-received'] ); } else if ( ! empty( $_GET['order-received'] ) ) { $plugin = 'wc'; $order_id = intval( $_GET['order-received'] ); } else if ( ! empty( $edd_receipt_args['id'] ) ) { $plugin = 'edd'; $order_id = $edd_receipt_args['id']; } else { return $can; } $hash = md5( $plugin . $order_id . $event ); $transient_key = sprintf( 'aepc_fired_%s', $hash ); if ( get_transient( $transient_key ) ) { return false; } set_transient( $transient_key, true ); return $can; }, 10, 2);
In this way, a transient is saved into the database with a unique combination of the plugin used, order ID and event name. Anyway, it’s not a definitive fix, I’ll think for something that I can include in the plugin, so keep an eye into the changelog of next releases and then remove this code after release the update that includes this fix! ?? Let me know if this snippet solves to you.
Furthermore, about the second issue, I’m not able to replicate the issue. I tried the AddToCart with EDD and I properly see the
content_name
set for the product that I added. Maybe it’s something related to a particular condition of your product or configuration of your store, are you able to investigate the cause of this issue? Let me know.Thanks.
@antoscarface – As someone with great deal of EDD experience, I’d say add a payment meta key for EDD. Check if it exists, if so do nothing, if not render purchase pixel and store a value to prevent it next time. Since meta is both cached and autoloaded there is no performance hit on future loads either.
Hope that helps.
@antoscarface – Took a crack at customizing the EDD portion of this as we are running tests now and double purchase hits are making testing near impossible to measure.
add_filter('aepc_can_track', function($can, $event) { if ( ! in_array( $event, array( 'purchase' ) ) || ! $can ) { return $can; } global $wp, $edd_receipt_args; // Get the Order ID if ( ! empty( $wp->query_vars['order-received'] ) ) { $plugin = 'wc'; $order_id = intval( $wp->query_vars['order-received'] ); } else if ( ! empty( $_GET['order-received'] ) ) { $plugin = 'wc'; $order_id = intval( $_GET['order-received'] ); } else if ( ! empty( $edd_receipt_args['id'] ) ) { $plugin = 'edd'; $order_id = $edd_receipt_args['id']; } else { return $can; } switch( $plugin ) { case 'wc': default: $hash = md5( $plugin . $order_id . $event ); $transient_key = sprintf( 'aepc_fired_%s', $hash ); if ( get_transient( $transient_key ) ) { return false; } set_transient( $transient_key, true ); break; case 'edd': if ( empty( $order_id ) || $order_id <= 0 ) { return false; } $payment = new EDD_Payment( $order_id ); if ( $payment->get_meta( 'aepc_fired_' . $event ) == true ) { return false; } $payment->update_meta( 'aepc_fired_' . $event, true ); break; } return $can; }, 10, 2);
@antoscarface – After further testing your original version and the last one I posted above didn’t track the purchase at all. I updated it based on some digging into EDD core & extension code and this is what I came up with that is a bit more complex but makes sure to disable it for non relevant views (fingers crossed). Waiting for confirmation after a few purcahses go through via the pixel dash.
add_filter( 'aepc_can_track', function ( $can, $event ) { if ( ! in_array( $event, array( 'purchase' ) ) || ! $can ) { return $can; } global $wp, $edd_receipt_args; $is_edd_enabled = function_exists( 'edd_is_success_page' ); $is_wc_enabled = function_exists( 'wc' ); if ( ! $is_edd_enabled && ! $is_wc_enabled ) { return $can; } // Get the Order ID if ( $is_wc_enabled ) { // skip pixel payment confirmation page and non success pages. if ( empty( $wp->query_vars['order-received'] ) && empty( $_GET['order-received'] ) ) { return false; } $order_id = ! empty( $wp->query_vars['order-received'] ) ? intval( $wp->query_vars['order-received'] ) : intval( $_GET['order-received'] ); // Do something better for WooC Here likely. $hash = md5( 'wc' . $order_id . $event ); $transient_key = sprintf( 'aepc_fired_%s', $hash ); if ( get_transient( $transient_key ) ) { return false; } set_transient( $transient_key, true ); } else if ( $is_edd_enabled ) { // skip pixel payment confirmation page and non success pages. if ( ! edd_is_success_page() || isset( $_GET['payment-confirmation'] ) ) { return false; } $session = edd_get_purchase_session(); if ( isset( $_GET['payment_key'] ) ) { $payment_key = urldecode( $_GET['payment_key'] ); } else if ( $session ) { $payment_key = $session['purchase_key']; } elseif ( $edd_receipt_args['payment_key'] ) { $payment_key = $edd_receipt_args['payment_key']; } if ( ! isset( $payment_key ) ) { return false; } $payment_id = (int) edd_get_purchase_id_by_key( $payment_key ); $user_can_view = edd_can_view_receipt( $payment_key ); $guest_purchase = ! is_user_logged_in() && edd_is_guest_payment( $payment_id ); if ( ! $user_can_view && ! $guest_purchase ) { return false; } if ( get_post_meta( $payment_id, "aepc_fired_$event", true ) ) { return false; } update_post_meta( $payment_id, "aepc_fired_$event", true ); $payment = edd_get_payment( $payment_id ); // If the completion time wasn't in the last 10 minutes (very generous I think), then this isn't the initial viewing of the receipt. // For purchases prior to this codes implementation. if ( time() - strtotime( $payment->get_meta( '_edd_completed_date' ) ) > 600 ) { return false; } } return $can; }, 10, 2 );
@antoscarface – No go, that still doesn’t fire the pixels. I am leaning toward having to setup a test locally to track this down with xdebug unless you see a reason it would never render the pixel purchase events.
Hey man,
I tested your previous suggestion, this:
add_filter('aepc_can_track', function($can, $event) { if ( ! in_array( $event, array( 'purchase' ) ) || ! $can ) { return $can; } global $wp, $edd_receipt_args; // Get the Order ID if ( ! empty( $wp->query_vars['order-received'] ) ) { $plugin = 'wc'; $order_id = intval( $wp->query_vars['order-received'] ); } else if ( ! empty( $_GET['order-received'] ) ) { $plugin = 'wc'; $order_id = intval( $_GET['order-received'] ); } else if ( ! empty( $edd_receipt_args['id'] ) ) { $plugin = 'edd'; $order_id = $edd_receipt_args['id']; } else { return $can; } switch( $plugin ) { case 'wc': default: $hash = md5( $plugin . $order_id . $event ); $transient_key = sprintf( 'aepc_fired_%s', $hash ); if ( get_transient( $transient_key ) ) { return false; } set_transient( $transient_key, true ); break; case 'edd': if ( empty( $order_id ) || $order_id <= 0 ) { return false; } $payment = new EDD_Payment( $order_id ); if ( $payment->get_meta( 'aepc_fired_' . $event ) == true ) { return false; } $payment->update_meta( 'aepc_fired_' . $event, true ); break; } return $can; }, 10, 2);
It works for me, are you able to test it again? Might it be some cache? Let me know.
@antoscarface – I will give it a shot. That said we use WP Engine and caching is disabled for EDD Checkout and logged in users. Should be disabled for purchase receipts as well honestly.
That said it had to have been processing before without success. To clarify when this code and the other was activated before I could see the Add to cart and that they began filling out purchase fields, but never purchase itself.
Likely gonna set up xdebig and track it down locally.
That said the second and last example is likely the better of the two and is exactly how other plugins are preventing double hits ( analytics, other pixels we use etc)
@antoscarface – Just tested this thoroughly with XDebug. It seems to be working correctly on local test. Will put it back on the live and see what happens.
add_filter( 'aepc_can_track', function ( $can, $event ) { if ( ! in_array( $event, array( 'purchase' ) ) || ! $can ) { return $can; } global $wp, $edd_receipt_args; $is_edd_enabled = function_exists( 'edd_is_success_page' ); $is_wc_enabled = function_exists( 'wc' ); if ( ! $is_edd_enabled && ! $is_wc_enabled ) { return $can; } // Get the Order ID if ( $is_wc_enabled ) { // skip pixel payment confirmation page and non success pages. if ( empty( $wp->query_vars['order-received'] ) && empty( $_GET['order-received'] ) ) { return false; } $order_id = ! empty( $wp->query_vars['order-received'] ) ? intval( $wp->query_vars['order-received'] ) : intval( $_GET['order-received'] ); // Do something better for WooC Here likely. $hash = md5( 'wc' . $order_id . $event ); $transient_key = sprintf( 'aepc_fired_%s', $hash ); if ( get_transient( $transient_key ) ) { return false; } set_transient( $transient_key, true ); } else if ( $is_edd_enabled ) { // skip pixel payment pending page (see: edd_paypal_success_page_content) and non success pages. if ( ! edd_is_success_page() || isset( $_GET['payment-confirmation'] ) ) { return false; } $session = edd_get_purchase_session(); if ( isset( $_GET['payment_key'] ) ) { $payment_key = urldecode( $_GET['payment_key'] ); } else if ( $session ) { $payment_key = $session['purchase_key']; } elseif ( ! empty( $edd_receipt_args['payment_key'] ) ) { $payment_key = $edd_receipt_args['payment_key']; } if ( ! isset( $payment_key ) ) { return false; } $payment_id = (int) edd_get_purchase_id_by_key( $payment_key ); $user_can_view = edd_can_view_receipt( $payment_key ); $guest_purchase = ! is_user_logged_in() && edd_is_guest_payment( $payment_id ); if ( ! $user_can_view && ! $guest_purchase ) { return false; } if ( get_post_meta( $payment_id, "aepc_fired_$event", true ) ) { return false; } update_post_meta( $payment_id, "aepc_fired_$event", true ); $payment = edd_get_payment( $payment_id ); // If the completion time wasn't in the last 10 minutes (very generous I think), then this isn't the initial viewing of the receipt. // For purchases prior to this codes implementation. if ( time() - strtotime( $payment->get_meta( '_edd_completed_date' ) ) > 600 ) { return false; } } return $can; }, 10, 2 );
Ok great, let me know if it works also in production. It must be something related to the configuration, cache or something other.
- The topic ‘Creating duplicate edd purchase events’ is closed to new replies.