Enhanced Ecommerce Tracking With Google Tag Manager in aMember

If you are using Google Tag Manager (GTM) to handle your Google Analytics, then you will need a way to populate the dataLayer with eCommerce data when you make a sale in your aMember site.

Here’s how I do it on my sites, using aMember’s own Conversion Track plugin.

Step 1: Add the dataLayer in Conversion Track plugin settings

NB: If you don’t have Conversion Track, you can order it from the “Addons Shop” in your aMember account.

I use two versions of the code so that initial payments are tracked separately to rebills. Here are the two code snippets in full:

Sale Tracking Code (For rebills)

<script>
// Sends transaction data with a pageview (DOM Ready)
dataLayer.push({
  'event': 'amPurchase',
  'ecommerce': {
    'currencyCode': '%payment.currency%',
    'purchase': {
      'actionField': {
        'id': '%payment.transaction_id%', // Transaction ID. Required for purchases and refunds.
        'affiliation': '%afflogin%',
        'revenue': '%payment.amount%',    // Total transaction value (incl. tax and shipping)
        'tax':'%payment.tax%',
        'shipping': '%payment.shipping%',
        'coupon': '%invoice.coupon_code%'
      },
      'products': [
           // List of productFieldObjects.
           %foreach_product%{
           'name': '%item.item_title%',       // Name or ID is required.
           'id': '%item.item_id%',
           'category': 'Rebill', 
           'price': '%item.second_total%',
           'quantity': '%item.qty%',
           'coupon': '%invoice.coupon_code%'  // Optional fields may be omitted or set to empty string.
           },%endforeach_product%
       ]
    }
  }
});
</script>

First Sale Tracking Code

<script>
// Sends transaction data with a pageview (DOM Ready)
dataLayer.push({
  'event': 'amPurchase',
  'ecommerce': {
    'currencyCode': '%payment.currency%',
    'purchase': {
      'actionField': {
        'id': '%payment.transaction_id%', // Transaction ID. Required for purchases and refunds.
        'affiliation': '%afflogin%',
        'revenue': '%payment.amount%',    // Total transaction value (incl. tax and shipping)
        'tax':'%payment.tax%',
        'shipping': '%payment.shipping%',
        'coupon': '%invoice.coupon_code%'
      },
      'products': [
           // List of productFieldObjects.
           %foreach_product%{
           'name': '%item.item_title%',       // Name or ID is required.
           'id': '%item.item_id%',
           'category': 'Initial Sale', 
           'price': '%item.first_total%',
           'quantity': '%item.qty%',
           'coupon': '%invoice.coupon_code%'  // Optional fields may be omitted or set to empty string.
           },%endforeach_product%
       ]
    }
  }
});
</script>

If you look carefully, the snippets only vary in the product category (“Rebill” vs “Initial Sale”) and product price, as aMember can charge a separate amount initially (e.g. $1 trial).

Step 2: Setup the Event Trigger in GTM

You may have noticed that my dataLayer snippets use an event to ensure the data is sent to GTM, so you will need to implement a custom event trigger called amPurchase in your GTM so that it knows what to do when aMember updates the dataLayer with your conversion data.

Here’s what mine looks like:

Step 3: Attach a UA Transaction Tag To The Trigger

Again, here’s what mine looks like:

And that’s it!

ClickBank IPN with PHP 7.2 and above

ClickBank’s Instant Notification Service is a webhook that lets you get transaction notifications in real time.

For example, you can use them to inform your membership software when members join/pay/cancel.

ClickBank provides the following sample code for PHP:

<?php
// NOTE: the mcrypt libraries need to be installed and listed as an
// available extension in your phpinfo() to be able to use this
// method of decryption.
 
$secretKey = "YOUR SECRET KEY"; // secret key from your ClickBank account
 
// get JSON from raw body...
$message = json_decode(file_get_contents('php://input'));
 
// Pull out the encrypted notification and the initialization vector for
// AES/CBC/PKCS5Padding decryption
$encrypted = $message->{'notification'};
$iv = $message->{'iv'};
error_log("IV: $iv");
 
// decrypt the body...
$decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128,
 substr(sha1($secretKey), 0, 32),
 base64_decode($encrypted),
 MCRYPT_MODE_CBC,
 base64_decode($iv)), "\0..\32");
error_log("Decrypted: $decrypted");
 
////UTF8 Encoding, remove escape back slashes, and convert the decrypted string to a JSON object...
$sanitizedData = utf8_encode(stripslashes($decrypted));
$order = json_decode($decrypted);
 
// Ready to rock and roll - If the decoding of the JSON string wasn't
// successful, then you can assume the notification wasn't encrypted
// with your secret key.
 
?>

The problem is that the mcrypt libraries – required to decrypt the notification – were abandoned back in 2007, and because of this, use of the library has been deprecated in PHP 7.1 and removed from PHP 7.2 entirely.

In other words, the minute your web host upgrades to PHP 7.2 or higher, you’ll find your membership site is totally unable to decode and read ClickBank’s notifications.

The answer is to switch to using the more modern OpenSSL instead.

The problematic part of ClickBank’s sample code is the mcrypt_decrypt() operation here:

// decrypt the body...
$decrypted = trim(mcrypt_decrypt(MCRYPT_RIJNDAEL_128,
 substr(sha1($secretKey), 0, 32),
 base64_decode($encrypted),
 MCRYPT_MODE_CBC,
 base64_decode($iv)), "\0..\32");

The OpenSSL equivalent is:

// decrypt the body...
$decrypted = trim(openssl_decrypt(
 base64_decode($encrypted),
 'aes-256-cbc',
 substr(sha1($secretKey), 0, 32),
 OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING,
 base64_decode($iv)), "\0..\32");

Here’s the entire updated code sample:

<?php
// NOTE: the mcrypt libraries need to be installed and listed as an
// available extension in your phpinfo() to be able to use this
// method of decryption.
 
$secretKey = "YOUR SECRET KEY"; // secret key from your ClickBank account
 
// get JSON from raw body...
$message = json_decode(file_get_contents('php://input'));
 
// Pull out the encrypted notification and the initialization vector for
// AES/CBC/PKCS5Padding decryption
$encrypted = $message->{'notification'};
$iv = $message->{'iv'};
error_log("IV: $iv");
 
// decrypt the body...
$decrypted = trim(openssl_decrypt(
 base64_decode($encrypted),
 'aes-256-cbc',
 substr(sha1($secretKey), 0, 32),
 OPENSSL_RAW_DATA|OPENSSL_ZERO_PADDING,
 base64_decode($iv)), "\0..\32");
error_log("Decrypted: $decrypted");
 
////UTF8 Encoding, remove escape back slashes, and convert the decrypted string to a JSON object...
$sanitizedData = utf8_encode(stripslashes($decrypted));
$order = json_decode($decrypted);
 
// Ready to rock and roll - If the decoding of the JSON string wasn't
// successful, then you can assume the notification wasn't encrypted
// with your secret key.
 
?>

Hope this saves you some time and hassle.

Center Align Featured Images in Genesis

One of the things that bugs me about the featured image setting in the Genesis framework is that you can only choose left or right align… you can’t center align!

Center Align Featured Images in Genesis

Of course, if I always used images that were all exactly the right size and aspect ratio on my Genesis based sites (all the newer ones), then it wouldn’t be an issue…

But that’s not always practical, and if the featured image is a little smaller than expected, then left align can leave you with text floating off the right hand side of the image like so…

align-woes-in-genesis

Here is the solution that I like to use, which filters the entry_image attributes and replaces alignleft with aligncenter.

You simply drop it into your theme functions.php and it’s done!

//* Center Image Alignment for Featured Image
function rjw_center_image_alignment( $attributes ) {
  $attributes['class'] = str_replace( 'alignleft', 'aligncenter', $attributes['class'] );
	return $attributes;
}
add_filter( 'genesis_attr_entry-image', 'rjw_center_image_alignment' );

Kudos to Genesis genius, Bill Erickson, for the code hint!

Screen sharing in OSX Mountain Lion Fix

After upgrading to Apple OSX Mountain Lion, I found that I was unable to connect to the upgraded mac via Screen Sharing any more.

After searching in vain for solutions, in desperation I decided to play with the screen sharing settings in case there was a new option or something.

In the end I was able to get it working again like so:

  1. Open the ‘Computer Settings’ option (System Preferences > Sharing > Screen Sharing)
  2. Change the ‘Anyone May request permission to control screen’ and Save.
  3. Open the ‘Computer Settings’ again and return the setting to it’s original state and Save again.
  4. Stop and start Screen Sharing in the Sharing Screen

It seems that the upgrade may have left the screen sharing settings in an unusable state, and simply re-saving the settings as above was enough to kick it into life again.

Your mileage may vary – but hope putting this ‘out there’ is useful to you too.

Installing the H264 Streaming Module on a cpanel server

The H264 Streaming Module is a webserver plugin that enables HTTP pseudo-streaming – the technology that allows you to jump to any part of a video regardless of whether it has been downloaded yet.

This post is mostly an aide-memoire for us, but putting it ‘out there’ in case it’s useful to others too.

HTTP pseudo-streaming – what is it?

HTTP Pseudostreaming lets you play back MP4 and FLV videos in portions – this means your video viewers can seek to parts of a video which have not yet been downloaded (as you can do on YouTube).

It’s useful for browsers which require flash mode (as HTML5 browsers can pseudo-stream automatically), and because it uses HTTP, your videos will work regardless of firewall settings.

For full information, please see the excellent article on the JW PLayer site.

Installing the H264 Streaming Module on a Cpanel server

1) Login as root to the server via ssh.

2) Switch to your home directory, download and unpack the Module.

cd ~
wget http://h264.code-shop.com/download/apache_mod_h264_streaming-2.2.7.tar.gz
tar -zxvf apache_mod_h264_streaming-2.2.7.tar.gz
cd ~/mod_h264_streaming-2.2.7

NB: This example is for version 2.2.7. Check on the CodeShop website to ensure it is still the latest version 😉

2) Configure and install the module.

./configure
make
sudo make install

The installer will hopefully install in the /usr/local/apache/modules directory, but double check by looking at the information in the last 20 or so lines of the output!

----------------------------------------------------------------------
Libraries have been installed in:
/usr/local/apache/modules

NB: If you get the following error:

** Unrecoverable Error **
The C compiler is not functional and auto repair failed.
Perl module installs require a working C compiler.
Please repair the C compiler and try again.

Chances are it’s a problem with the permissions on the /tmp folder. It should be owned by “root” and have 1777 permissions.
The permissions can be set via:

# chmod 1777 /tmp

 

3) Now include the module in the Apache configuration.

There are two ways to do this – via command line, or via WHM. We’re already in shell, so lets look at that way first.

a) Via Shell, using the vi text editor

vi /usr/local/apache/conf/includes/pre_main_global.conf

One in vi, hit the ‘i‘ key to enter insert mode and paste the following:

LoadModule h264_streaming_module /usr/local/apache/modules/mod_h264_streaming.so
AddHandler h264-streaming.extensions .mp4

NB: If the module was installed in a different directory to /usr/local/apache/modules/ then adjust accordingly!

Now save the file – hit ESC key to exit insert mode, then type the following to save and quit.

:wq

Finally, rebuild the config file and restart apache

/usr/local/cpanel/bin/build_apache_conf
service httpd restart

b) Via WHM

Select “Apache Configuration”

Select “Include Editor”

Under “Pre-Main Include” select “All Versions”.

Enter the following:

LoadModule h264_streaming_module /usr/local/apache/modules/mod_h264_streaming.so
AddHandler h264-streaming.extensions .mp4

NB: Again, checking the path to module is ok.

Select ‘Update’ and follow instruction to restart apache.

4) Finally, if you are using it commercially, you need to get a licence
(€39 for single webserver at time of writing)