• 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.
Viewing 10 replies - 1 through 10 (of 10 total)
  • Thread Starter Daniel Iser

    (@danieliser)

    Also while looking at EDD events, the AddToCart event has the proper content_type, content_ids & value, but the content_name shows as Not Set rather than the product name.

    Plugin Author Antonino Scarfì

    (@antoscarface)

    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.

    Thread Starter Daniel Iser

    (@danieliser)

    @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.

    Thread Starter Daniel Iser

    (@danieliser)

    @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);
    Thread Starter Daniel Iser

    (@danieliser)

    @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 );
    Thread Starter Daniel Iser

    (@danieliser)

    @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.

    Plugin Author Antonino Scarfì

    (@antoscarface)

    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.

    Thread Starter Daniel Iser

    (@danieliser)

    @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)

    Thread Starter Daniel Iser

    (@danieliser)

    @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 );
    Plugin Author Antonino Scarfì

    (@antoscarface)

    Ok great, let me know if it works also in production. It must be something related to the configuration, cache or something other.

Viewing 10 replies - 1 through 10 (of 10 total)
  • The topic ‘Creating duplicate edd purchase events’ is closed to new replies.