Skip to content

Commit

Permalink
Merge pull request #188 from Recras/ga4-support
Browse files Browse the repository at this point in the history
Add support for Google Analytics v4 (GA4)
  • Loading branch information
timmipetit authored Apr 1, 2022
2 parents 2e070a4 + 9bd34de commit e2fa726
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 10 deletions.
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ The library sends out a few custom events when certain things change:
You can use these events for custom actions, such as analytics. For use in code, please refer to
the constants in [src/eventHelper.js](src/eventHelper.js).
When Google Analytics integration is enabled, certain events sent to GA include a label and/or value:
When Google Analytics integration is enabled, certain events are sent to GA. Which events are sent depends on the version of GA you are using. For Universal Analytics (v3) and older, these custom events are sent and they include a label and/or value:
| Event | Label | Value |
| ---------------------------------- | --------------------------------- |-------------------------------------|
Expand All @@ -140,3 +140,8 @@ When Google Analytics integration is enabled, certain events sent to GA include
| `Recras:Voucher:TemplateChanged` | N/A | Template ID |
| `Recras:Voucher:BuyInProgress` | Template name | Rounded total amount of the order |
| `Recras:Voucher:RedirectToPayment` | N/A | Rounded total amount of the order |
For GA4, these events are sent:
* when a package is selected: `select_content`. The ID of the package is included.
* when a voucher is selected: `select_content`. The ID of the template is included.
* when the user is redirected to the payment provider: `begin_checkout`. The total amount as well as all selected items (name, price, quantity) are included.
50 changes: 48 additions & 2 deletions src/booking.js
Original file line number Diff line number Diff line change
Expand Up @@ -318,7 +318,11 @@ class RecrasBooking {
RecrasEventHelper.PREFIX_BOOKING,
RecrasEventHelper.EVENT_BOOKING_PACKAGE_CHANGED,
selectedPackage[0].arrangement,
selectedPackage[0].id
selectedPackage[0].id,
{
content_type: 'package',
item_id: selectedPackage[0].id,
}
);
}
this.selectedPackage = selectedPackage[0];
Expand Down Expand Up @@ -1375,6 +1379,43 @@ ${ msgs[1] }</p></div>`);
return attachments;
}

formatGA4Items() {
let items = [];

if (this.bookingSize() > 0) {
let pck = this.selectedPackage;
items.push({
item_name: (pck.weergavenaam || pck.arrangement),
price: this.bookingSizePrice(pck),
quantity: this.bookingSize(),
});
}

let linesNoBookingSize = this.getLinesNoBookingSize(this.selectedPackage);
linesNoBookingSize = linesNoBookingSize.filter(line => {
const lineEl = this.findElement(`[data-package-id="${ line.id }"]`);
if (!lineEl) {
return false;
}

if (isNaN(parseInt(lineEl.value))) {
return false;
}
return parseInt(lineEl.value) > 0;
});
linesNoBookingSize = linesNoBookingSize.map(line => {
const lineEl = this.findElement(`[data-package-id="${line.id}"]`);
return {
item_name: line.beschrijving_templated,
price: line.product.verkoop,
quantity: parseInt(lineEl.value),
};
});
items.push(...linesNoBookingSize);

return items;
}

submitBooking() {
let productCounts = this.productCounts().map(line => line.aantal);
let productSum = productCounts.reduce((a, b) => a + b, 0);
Expand Down Expand Up @@ -1432,7 +1473,12 @@ ${ msgs[1] }</p></div>`);
RecrasEventHelper.PREFIX_BOOKING,
RecrasEventHelper.EVENT_BOOKING_REDIRECT_PAYMENT,
null,
Math.round(this.getTotalPrice())
Math.round(this.getTotalPrice()),
{
currency: this.languageHelper.currency,
value: this.getTotalPrice(),
items: this.formatGA4Items(),
}
);
window.top.location.href = json.payment_url;
} else if (json.redirect) {
Expand Down
37 changes: 32 additions & 5 deletions src/eventHelper.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,26 @@ class RecrasEventHelper {
return this.eventsEnabled.includes(name);
}

sendEvent(cat, action, label = undefined, value = undefined) {
ga4EventMap(action) {
let map = {
[RecrasEventHelper.EVENT_BOOKING_PACKAGE_CHANGED]: 'select_content',
[RecrasEventHelper.EVENT_BOOKING_REDIRECT_PAYMENT]: 'begin_checkout',
[RecrasEventHelper.EVENT_VOUCHER_TEMPLATE_CHANGED]: 'select_content',
[RecrasEventHelper.EVENT_VOUCHER_REDIRECT_PAYMENT]: 'begin_checkout',
};

if (map[action] === undefined) {
return false;
}
return map[action];
}

isGA4() {
const fn = window[window.GoogleAnalyticsObject || 'ga'];
return fn && fn.h && fn.h.gtm4;
}

sendEvent(cat, action, label = undefined, value = undefined, ga4Value = undefined) {
let event;

try {
Expand All @@ -60,8 +79,11 @@ class RecrasEventHelper {
}

if (this.analyticsEnabled && this.eventEnabled(action)) {
if (typeof window.gtag === 'function') {
// Global Site Tag - the more modern variant
if (this.isGA4() && this.ga4EventMap(action) && ga4Value) {
// v4
this.sendGA4Event(this.ga4EventMap(action), ga4Value);
} else if (typeof window.gtag === 'function') {
// Global Site Tag (v4)
let eventData = {
event_category: RecrasEventHelper.PREFIX_GLOBAL + ':' + cat,
};
Expand All @@ -73,7 +95,7 @@ class RecrasEventHelper {
}
window.gtag('event', action, eventData);
} else if (typeof window.ga === 'function') {
// "Old" Google Analytics
// "Old" Google Analytics (v2) and Tag Manager
let eventData = {
hitType: 'event',
eventCategory: RecrasEventHelper.PREFIX_GLOBAL + ':' + cat,
Expand All @@ -92,13 +114,18 @@ class RecrasEventHelper {
prefix += '.';
}
window.ga(prefix + 'send', eventData);
})
});
}
}

return document.dispatchEvent(event);
}

sendGA4Event(action, data) {
const fn = window[window.GoogleAnalyticsObject || 'ga'];
fn('event', action, data);
}

setAnalytics(bool) {
this.analyticsEnabled = bool;
}
Expand Down
23 changes: 21 additions & 2 deletions src/vouchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,16 @@ class RecrasVoucher {
this.element.insertAdjacentHTML('beforeend', msg);
}

formatGA4Item() {
return [
{
item_name: this.selectedTemplate.name,
price: this.selectedTemplate.price,
quantity: parseInt(this.findElement('#number-of-vouchers').value),
}
];
}

buyTemplate() {
let status = this.contactForm.checkRequiredCheckboxes();
if (!status) {
Expand Down Expand Up @@ -72,7 +82,12 @@ class RecrasVoucher {
RecrasEventHelper.PREFIX_VOUCHER,
RecrasEventHelper.EVENT_VOUCHER_REDIRECT_PAYMENT,
null,
Math.round(this.totalPrice())
Math.round(this.totalPrice()),
{
currency: this.languageHelper.currency,
value: this.totalPrice(),
items: this.formatGA4Item(),
}
);
window.top.location.href = json.payment_url;
} else {
Expand All @@ -94,7 +109,11 @@ class RecrasVoucher {
RecrasEventHelper.PREFIX_VOUCHER,
RecrasEventHelper.EVENT_VOUCHER_TEMPLATE_CHANGED,
null,
templateID
templateID,
{
content_type: 'voucher',
item_id: templateID,
}
);
}

Expand Down

0 comments on commit e2fa726

Please sign in to comment.