Sådan spores brugen af oversættelses-plugins med Google Analytics 4

.
Tags: GA4, Google Tag Manager

Jeg diskuterede forleden med en kunde, hvorvidt der bør tilføjes en Google Translate-funktion til deres website. I første omgang ville vi lave funktionen og A/B-teste dens effekt på konvertering. Men inden, vi kunne komme dertil, ville vi først undersøge, hvor ofte vores brugere oversætter websitet vha. de indbyggede værktøjer i forskellige browsere.

Hvad er browser-oversættelse?

Alle de store browsere på markedet har indbyggede funktioner til at oversætte en given side til et givent sprog. Både Safari og Edge undersøger automatisk om en given side er på et sprog, der er anderledes end det sprog, som er indstillet i brugerens operativsystem.

Når det er tilfældet, giver de browsere besked til brugeren om, at siden kan oversættes.

I andre browsere, fx Chrome og Firefox, kan brugere selv installere browser-udvidelser. Det er typisk Google Translate, der installeres.

Det er anvendelsen af disse oversættelsesfunktioner og -værktøjer, som vi gerne vil spore.

Hvordan virker oversættelsesværktøjer?

Helt overordnet, sker der nogle ganske få ting, når brugeren aktiverer et oversættelsesværktøj i browseren. For det første identificerer browseren alle (HTML) elementer på siden, som indeholder tekst. Hver af disse tekster sendes til et oversættelses-API, som returnerer de oversatte tekster. Og de tekster indsættes så i de oprindelige HTML-elementer.

Når man bruger Google Translate eller de indbyggede funktioner i Safari og Edge, så sker dette fuldstændig gnidningsløst - faktisk opdateres siden ikke engang.

Hvordan ser vi, om oversættelse anvendes?

Uanset hvilken analytics-platform man bruger, så må det første skridt være at identificere det øjeblik, en bruger aktiverer en oversættelsesfunktion. For den kunde, jeg arbejdede med, sendte vi et event til Google Analytics 4 - men fremgangsmåde er den samme for enhver platform.

Uanset hvad, så skulle der kun lidt begrænset detektivarbejde til i udviklerkonsollen for at nå frem til metoden. For alle de undersøgte værktøjer (Safari, Edge og Google Transate) viser det sig, at de alle foretager nogle simple ændringer i DOM’en, når de aktiveres. Og som bekendt: Alt, hvad der foregår i DOM’en er som regel noget, vi kan spore.

For eksempel sker dette, når man aktiverer Microsoft Edge’s oversættelsesfunktion:

<!-- Oprindeligt tysk title tag: -->
<title>DER SPIEGEL | Online-Nachrichten</title>

<!-- Title tag der nu er oversat til engelsk: -->
<title _msthash="149916" _msttexthash="439634">DER SPIEGEL | Online News</title>

Microsoft Edge tilføjer faktisk de to attributter (_msthash and _msttexthash) til samtlige HTML-elementer, der oversættes.

Google Translate opfører sig på en lignende måde (uanset browser) og laver en mindre ændring i <html> tag’et:

<!-- Google Translate tilføjer en enkelt class til <html> tag'et -->
<html class="translated-ltr">

Safari er en anelse mere subtil, men laver faktisk også bare en attribut-ændring på <html> tag’et, hvor den enten ændrer den eksisterende eller tilføjer en lang attribut:

<!-- Safari ændrer lang-attributten på <html> tag'et -->
<html lang="en-US">

So it appears that various translation tools put a pretty visible mark on the pages they translate. The one remaining problem is that these changes to the HTML occur seamlessly without a page refresh or any other tangible event. This means that we can’t reliably just look for the presence of these attributes or values when a page loads.

Instead, we need to monitor if these changes occur at any time while the user is on a given page. Luckily, modern browsers implement the MutationObserver API which is built for exactly that; namely monitoring changes to elements in real time.

I’ll spare you for too much of the technical stuff, so please make do with this (commented code). You might want to copy it to your own code editor for increased readability:

(function(){
    // Start by checking if the MutationObserver API is available
    if( typeof MutationObserver === 'function') {
        // Tell the observer to monitor for changes to HTML attributes
        var config = { attributes: true };
        // Build the function to run when a change is observed
        var callback = function(mutationList, observer) {
            // Loop through each observed change (using old school loop as ES6 is still not supported in GTM)
            for(var i = 0; i < mutationList.length; i++) {
                // Only do something if the change was on an attribute
                if (mutationList[i]['type'] === 'attributes') {
                    if(
                        // Check for Edge's attributes
                        mutationList[i]['attributeName'] === '_msthash' || mutationList[i]['attributeName'] == '_msttexthash' ||
                        // Check for Google Translate's class
                        (mutationList[i]['attributeName'] === 'class' && mutationList[i]['target'].className.substring(0,9) == 'translate') ||
                        // Check for Safari's lang attribute
                        mutationList[i]['attributeName'] === 'lang'
                    ) {
                        // Stop observing to only track once per page
                        // On an SPA site, you might want to remove this line if you want to track the event on all pages
                        observer.disconnect();
                        // Send an event to the dataLayer (or do whatever you want)
                        window.dataLayer = window.dataLayer || [];
                        window.dataLayer.push({
                            'event': 'translate'
                        });
                    }
                }
                break;
            }
        };
        // Create the actual observer
        var observer = new MutationObserver(callback);
        // Attach the observer to the <title> tag
        observer.observe(document.getElementsByTagName('title')[0], config);
        // Attach the observer to the <html> tag
        observer.observe(document.getElementsByTagName('html')[0], config);
    }
})();

This piece of javascript can be enabled inline or in an external js file - or included in your tag manager of choice. For Google Tag Manager, simply insert this on all pages using a Custom HTML tag (and remember to add <script> before the code, and </script> after the code).

Obviously, if your site has features or tools that alter the HTML in the same way as these translations tool do, those changes will be captured too. If that’s the case, you’d need more specificity in the code.

Setup the GTM configuration

The rest is straightforward: Create a new trigger in GTM to capture the translate event:

GTM trigger to capture translate event

And then configure a new GA4 Event tag:

Send a GA4 translation event

And that’s it. GA4 will now begin to collect events on any page where users enable translations.

For example, setup a free form report to examine how often users enable translations. In this example (screenshot below), I have inserted a custom dimension called Site Language (on this particular multilingual site, we track the currently selected language). This report simply tells us that the language most often being translated into something else is actually English. Which came as a bit of a surprise.

GA4 translation free form report

And thanks for reading this far! :)