The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Net::Google::Analytics::MeasurementProtocol - send Google Analytics (GA4) user interaction data from Perl

SYNOPSIS

    use Net::Google::Analytics::MeasurementProtocol;

    my $ga = Net::Google::Analytics::MeasurementProtocol->new(
        api_secret     => '...',
        measurement_id => '...',
    );

    $ga->send( level_up => { character => 'Alma', level => 99 } );

    $ga->send_multiple([
        {
            purchase => {
                transaction_id => 'T-1234',
                currency       => 'USD',
                value          => 14.99,
                coupon         => 'SPECIALPROMO',
                shipping       => 2.99,
                tax            => 0.37,
                items          => [
                    { item_id => 'X-1234', item_name => 'Amazing Tee' },
                    { item_id => 'Y-4321', item_name => 'Cool Shades' },
                ],
            },
        },
        {
            earn_virtual_currency => {
                virtual_currency_name => 'StoreCash',
                value => 999,
            },
        },
    ]);

DESCRIPTION

This is a Perl interface to Google Analytics Measurement Protocol, allowing developers to make HTTP requests to send raw user interaction data directly to Google Analytics 4 (GA4) servers. It can be used to tie online to offline behaviour, sending analytics data from both the web (via JavaScript) and from the server (via this module).

WARNING - BACKWARDS INCOMPATIBLE

This distribution follows the next generation Google Analytics 4 (GA4), which is completely different from previous versions like GA3 and Universal Analytics (UA). As of 2023, Google has not only deprecated but completely removed these older versions of Analytics, and your code (and ours) must adapt to theses changes. If you are upgrading, please review your code.

CONSTRUCTOR

new( %options )

new( \%options )

    my $ga = Net::Google::Analytics::MeasurementProtocol->new(
        api_secret     => '...',
        measurement_id => '...',
    );

Creates a new object with the provided information. There are many options to customize its behaviour:

Required parameters:

  • api_secret String. This is the API Secret key generated manually via the Google Analytics UI. To create one, go to: Admin > Data Streams > choose your stream > Measurement Protocol API Secrets > Create

  • measurement_id String. This is the identifier for your target Data Stream. You can find yours on the Google Analytics UI under: Admin > Data Streams > choose your stream > Measurement ID

Parameters with default values

  • agent Object that handles requests/responses. May be a Furl instance, an LWP::UserAgent instance, or anything that inherits from them, like WWW::Mechanize, or that provides a similar request/response interface AND is able to handle HTTPS. Defaults to a Furl instance. Also, please make sure your object contains a default header of 'Content-Type' set to 'application/json'.

  • client_id String. Uniquely identify a user instance. Defaults to a random UUID created for this object (staying the same for as long as the object lives).

    NOTE: Google states that events are only valid if they contain a client_id that has already been used to send an event from gtag.js. While we haven't seen this constraint in our tests, you are probably better off setting this yourself. Please see TROUBLESHOOTING for further information.

Other parameters

There are many, many parameters available. Please refer to the official Measurement Protocol Parameter Reference for details.

METHODS

send( $event_name, \%event_params )

Sends an event to Google Analytics (GA4). You may send any custom event name or one of Google's accepted events and their associated parameters.

NOTE: This method will return a true value if the HTTP request to GA4 was properly received and false otherwise, but this DOES NOT MEAN the event was accepted. The Measurement Protocol will not tell you if the payload data was malformed, incorrect or not processed by Google Analytics for whatever reason. See TROUBLESHOOTING for more information on how to check if you are sending the proper data.

NOTE: For your custom events to show up in standard GA4 reports (like Realtime), you must pass the engagement_time_msec and session_id parameters to the event. Ex:

    $ga->send( offline_purchase => { session_id => '123', engagement_time_msec => 100 } );

send_multiple( [ { event1 => \%params }, { event2 => \%params }, ... ] )

This method allows you to send a batch of events in a single HTTP request. It is much more efficient than calling send() several times.

Like send(), it returns true if the request reached GA4 servers, and false otherwise.

TROUBLESHOOTING

Google Analytics offers a validation server for your hits, without risk of damaging your production analytics data. To access it, simply set the 'debug' flag to true when creating the object:

    my $ga = Net::Google::Analytics::MeasurementProtocol->new(
        api_secret     => '1234',
        measurement_id => '4321',
        debug          => 1,
    );

Now, calls to send() and send_multiple() will make the request to Google's validation servers and return a hash reference containing response information, which should indicate whether your request is valid or not and, if not, why it wasn't accepted. So you can do something like this:

    # assuming the 'debug' flag is on:
    my $res = $ga->send( 'join_group' => { group_id => 'knitters#666' } );

    use DDP; p $res;

Make sure you disable "debug" before going live. Debug requests are sent to a different route and do not show up in your Google Analytics!

Finally, if you have not passed a valid client_id to the constructor, you should try it. You can get a real one by adding the following JS snippet to your website's footer (or anywhere AFTER loading Google Analytics (GA4) scripts either inline or via tools like Google Tag Manager), then visiting it and inspecting the console log in your browser:

    <script>
      if(typeof gtag != 'function'){
        window.gtag = function() { dataLayer.push(arguments); }
      }
      gtag('get', 'YOUR_MEASUREMENT_ID_HERE', 'client_id', (client_id) => {
        console.log("client_id is " + client_id)
      });
    </script>

If even after all that your events are still not showing, please refer to Google's Troubleshoot Page for the Measuremnt Protocol.

KNOWN ISSUES

Right now it is not possible to send User Properties. Patches welcome!

This module also does not validate your input. Patches welcome!

SEE ALSO

Measurement Protocol for Google Analytics 4 (GA4)

Measurement Protocol Reference

GA4 Measurement Protocol - Validating Events

LICENSE AND COPYRIGHT

Copyright 2015-2023 Breno G. de Oliveira <garu at cpan.org>. All rights reserved.

This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself. See perlartistic.

Google and Google Analytics are trademarks of Google LLC.

This software is not endorsed by or affiliated with Google in any way.

DISCLAIMER OF WARRANTY

BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR, OR CORRECTION.

IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.