0
\$\begingroup\$

I am working on an e-commerce website.

I want to track 2 events in Google Analytics (I would need to send these events to Analytics):

  1. when a buyers contacts a sellers (an email will be sent through the website)
  2. when a job seeker applies for a job (job seeker would be redirected to the employer's website)

According to Google Documentation, I would need to send an event to Google Analytics using the code below:

gtag('event', 'aaa', {
  'event_category' : 'bbb',
  'event_label' : 'ccc'
});

So basically I need to put the above code on the onclick event of a button/link. Also note that I only want to trigger these events in the production environment.

My website is implemented in ASP.NET MVC, and I want to pass the following info as event name, event category and event label:

  • Event Name: email_sent or job_redirect
  • Category: Category of the product (for example: Sports > Team > Football or Jobs > IT > Programmer)
  • Event label: $"{BuyerName}, {SellerName}"

The Category, BuyerName and SellerName are not available in the PartialView which sends the email... I could change the PartialView Model and include this info... but I though it is easier to keep this information in the ViewBag and include it in the Layout so any page that want to send the event, can access this info.

So this is what I have done in the page Layout:

_layout.cshtml

<!DOCTYPE html>
<html lang="en-nz">
<head>
    @if (EnvironmentConfig.IsProdEnvironment)
    {
        <!-- Google Analytics -->
        <script async src="https://www.googletagmanager.com/gtag/js?id=UA-144340016-1"></script>
        <script>
            window.dataLayer = window.dataLayer || [];
            function gtag() { dataLayer.push(arguments); }
            gtag('js', new Date());
            gtag('config', 'UA-144340016-1');
        </script>
        <!-- End Google Analytics -->

        <meta name="ga_category" content="@ViewBag.GaCategory" />
        <meta name="ga_label" content="@ViewBag.GaLabel" />
    }

    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@ViewBag.Title</title>
    <meta name="description" content="@ViewBag.Description">
    // more code...

Obviously I need to set the ViewBag in every page that displays a product or job... I have decided to do this in the 'AdBaseController'... AdBase is the base class for all ad types... for example 'Job', 'Car', 'House' and 'Product' are all inherited from AdBase

AdBaseController.cs

[Authorize]
[AllowImpersonator]
public class AdBaseController : ShoplessBaseController
{
    protected void SetDisplayPageMetaData(AdBaseViewModel adBaseViewModel)
    {
        ViewBag.Title = adBaseViewModel.Title;
        ViewBag.Description = adBaseViewModel.OgDescription;
        ViewBag.Keywords = $"{adBaseViewModel.Title} {adBaseViewModel.CombinedCategoryViewModel.GetCombineCategoryName()}";

        if (EnvironmentConfig.IsProdEnvironment)
        {
            // used for Google Analytics events
            ViewBag.GaCategory = adBaseViewModel.CombinedCategoryViewModel.CategoryFullName;
            ViewBag.GaLabel = $"Buyer: {GetUserEmail()}";
        }

        if (adBaseViewModel.CombinedCategoryViewModel.UseOgImageForAd)
        {
            ViewBag.OgImageCanonicalUrl = adBaseViewModel.CombinedCategoryViewModel.OgImageCanonicalUrl;
        }
        else if (adBaseViewModel.Photos.Any() && adBaseViewModel.Photos[0] != null)
        {
            ViewBag.OgImageCanonicalUrl = ShoplessUrlHelper.GetCanonicalUrl(adBaseViewModel.MainPhotoAbsolutePath);
        }
    }
}

Now when I want to display any ad types (e.g. Job, Car, House, etc) I would have to call SetDisplayPageMetaData in the Display Action method, example:

JobController.cs

// [Authorize] <-- inherited from base
public class JobController : AdBaseController
{
    private readonly AdService<Job, JobViewModel> _adService;
    private readonly JobApplicationService _jobProfileService;

    public JobController(AdService<Job, JobViewModel> adService, AdCommonService adCommonService, JobApplicationService jobProfileService)
        : base(adCommonService)
    {
        _adService = adService;
        _jobProfileService = jobProfileService;
    }

    [HttpGet]
    [AllowAnonymous]
    public ActionResult Display(long adBaseId)
    {
        JobViewModel jobViewModel = _adService.GetActiveAd(adBaseId);
        
        if (jobViewModel != null)
        {
            SetDisplayPageMetaData(jobViewModel);
            var jobApplicationViewModel = _jobProfileService.GetJobApplicationViewModelIfAny(adBaseId, GetUserId());
            if (jobApplicationViewModel == null)
            {
                jobApplicationViewModel = new JobApplicationViewModel(adBaseId, GetUserFullName(), GetUserEmail());
            }
            
            SetViewBagContactModel(jobApplicationViewModel);
            return View(jobViewModel);
        }

        return RedirectToHomeWithAlert(new AdWasNotFoundAlert());
    }
}

So this is how I populate the event category and event label in all of the product display pages.

Now this is the partial view which displays a job... there is an Apply button that a candidate can click and he would be redirected to employer website...

_JobDisplayApplyButton.cshtml

@model JobViewModel
@{
    var userId = (((ClaimsPrincipal)User).Identity.GetUserId<long>());
}

@if (userId != Model.UserProfileViewModel.UserId)
{
    if (string.IsNullOrEmpty(Model.ExternalApplicationUrl))
    {
        <div class="form-row">
            <div class="form-group col-12">
                <button id="openContactModalButton" class="btn btn-primary-action w-100" data-target="#contactModal">
                    <i class="fa fa-comments-o"></i>
                    <span>Apply</span>
                </button>
                @if (userId > 0)
                {
                    // only logged in users can open the contact modal, those not logged in will be redirected to login page, this is done in communication.js
                    @Html.Partial("ContactModalComponents/_JobContactModal", Model)
                }
            </div>
        </div>
    }
    else
    {
        <div class="form-row">
            <div class="form-group col-12">

    <!-- Note that I have decided that I don't want to put the onClick directly on the link,
         but instead I want to put all the Google analytics events in a single .js file, so 
         not using the code below:

                <a id="jobRedirectLinkId" href="@Model.ExternalApplicationUrl" class="btn btn-primary-action w-100" target="_blank" 
                   onclick="gtag('event', 'job_redirect', {'event_category': '@ViewBag.GaCategory', 'event_label': '@ViewBag.GaLabel'});">
    -->

                <a id="jobRedirectLinkId" href="@Model.ExternalApplicationUrl" class="btn btn-primary-action w-100" target="_blank">
                    <i class="fa fa-external-link"></i>
                    <span>Apply</span>
                </a>
            </div>
        </div>
    }
}

So now when the Apply link is clicked, I want to send an event to Google Analytics, I have put all of this code in the file below:

google-analytics-event.js

"use strict";

var isProdEnvironment = $('#isProdEnvironment').val();
var event_category = ''
var event_label = ''

function sendEvent(event) {
    if (event_category != '' || event_label != '') {
        gtag('event', event, {
            'event_category': event_category,
            'event_label': event_label
        });
    }
}

// events
// ------
function gaEventEmailSent() {
    sendEvent('email_sent');
}

function gaEventJobRedirect() {
    sendEvent('job_redirect');
}

// triggers
// --------
$("#jobRedirectLinkId").click(function () {
    gaEventJobRedirect();
});

// initialization
// --------------
$(document).ready(function () {
    if (isProdEnvironment == '1') {
            event_category = $("head > meta[name='ga_category']").val();
            event_label = $("head > meta[name='ga_label']").val();
        }
    }
});

And finally here is how I would trigger the email_sent event, this would happen when a message has been send successfully... I have a file called communication.js, in this file displaySendingMessageSpinner() is called when an email is being sent:

communication.js

function displaySendingMessageSpinner() {
    // in case of job application, message is optional, so we don't need to check user has entered a message
    displayModalOverlay();
    $('.sending-message-spinner').show();
    gaEventEmailSent(); <-- track this event in Google Analytics
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.