File Coverage

blib/lib/Net/Google/Analytics/MeasurementProtocol.pm
Criterion Covered Total %
statement 27 66 40.9
branch 0 18 0.0
condition 0 6 0.0
subroutine 7 12 58.3
pod 3 3 100.0
total 37 105 35.2


line stmt bran cond sub pod time code
1 3     3   134900 use v5.20;
  3         51  
2 3     3   15 use warnings;
  3         7  
  3         94  
3 3     3   17 use feature 'signatures';
  3         6  
  3         441  
4 3     3   29 no warnings qw(experimental::signatures);
  3         7  
  3         153  
5              
6 3     3   20 use Carp ();
  3         6  
  3         50  
7 3     3   2114 use JSON ();
  3         36919  
  3         2197  
8              
9             our $VERSION = 4.01;
10              
11             package Net::Google::Analytics::MeasurementProtocol {
12              
13 0     0 1 0 sub new ($class, %args) {
  0         0  
  0         0  
  0         0  
14             return bless {
15             api_secret => $args{api_secret},
16             measurement_id => $args{measurement_id},
17             client_id => $args{client_id} // _gen_uuid_v4(),
18             agent => $args{agent} // _build_user_agent(),
19             debug => $args{debug},
20 0   0     0 _route => _build_route(%args),
      0        
21             }, $class;
22             }
23              
24 0     0 1 0 sub send ($self, $name, $properties) {
  0         0  
  0         0  
  0         0  
  0         0  
25 0 0       0 Carp::croak('properties must be a hashref') unless ref $properties eq 'HASH';
26 0         0 return $self->send_multiple( [{ $name => $properties }] );
27             }
28              
29 0     0 1 0 sub send_multiple ($self, $events) {
  0         0  
  0         0  
  0         0  
30 0 0       0 Carp::croak('events must be an array reference') unless ref $events eq 'ARRAY';
31 0         0 my @formatted_events;
32 0         0 foreach my $e (@$events) {
33 0         0 my ($name, $params) = each %$e;
34 0         0 push @formatted_events, { name => $name, params => $params }
35             }
36              
37             my $payload = JSON::encode_json({
38             client_id => $self->{client_id},
39 0         0 events => \@formatted_events,
40             });
41              
42 0 0       0 my $res = $self->{agent}->post( $self->{_route}, $self->{agent}->isa('Furl') ? undef : (), $payload );
43 0 0       0 if ($res->is_success) {
44 0 0       0 return $self->{debug} ? JSON::decode_json($res->decoded_content) : 1;
45             }
46 0         0 return { __PACKAGE__ => $res->decoded_content };
47             }
48              
49 0     0   0 sub _build_route(%args) {
  0         0  
  0         0  
50 0 0       0 if ($args{tid}) {
51 0         0 Carp::croak('Looks like you are calling ' . __PACKAGE__ . ' with'
52             . ' outdated arguments from Universal Analytics. Please update'
53             . ' to Google Analytics 4 (GA4) accordingly');
54             }
55 0 0       0 if (!$args{api_secret}) {
56 0         0 Carp::croak('api_secret is required. Create one in Admin > Data Streams'
57             . ' > choose your stream > Measurement Protocol > Create');
58             }
59 0 0       0 if (!$args{measurement_id}) {
60 0         0 Carp::croak('measurement_id is required. Find yours under Admin > Data'
61             . ' Streams > choose your stream > Measurement ID');
62             }
63              
64 0 0       0 my $debug = $args{debug} ? '/debug' : '';
65             return 'https://www.google-analytics.com' . $debug . '/mp/collect'
66             . '?measurement_id=' . $args{measurement_id}
67 0         0 . '&api_secret=' . $args{api_secret};
68             }
69              
70             sub _build_user_agent {
71 0     0   0 require Furl;
72 0         0 return Furl->new( agent => __PACKAGE__ . '/' . $VERSION, timeout => 5, headers => ['Content-Type' => 'application/json'] );
73             }
74              
75             # UUID v4 (pseudo-random) generator based on UUID::Tiny
76             sub _gen_uuid_v4 {
77 2     2   82 my $uuid = '';
78 2         8 for ( 1 .. 4 ) {
79 8         24 my ($v1, $v2) = (int(rand(65536)) % 65536, int(rand(65536)) % 65536);
80 8         14 my $rand_32bit = ($v1 << 16) | $v2;
81 8         22 $uuid .= pack 'I', $rand_32bit;
82             }
83 2         9 substr $uuid, 6, 1, chr( ord( substr( $uuid, 6, 1 ) ) & 0x0f | 0x40 );
84 2         5 substr $uuid, 8, 1, chr( ord( substr( $uuid, 8, 1 ) ) & 0x3f | 0x80 );
85              
86             # uuid is created. Convert to string:
87 2         5 return join '-', map { unpack 'H*', $_ } map { substr $uuid, 0, $_, '' } ( 4, 2, 2, 2, 6 );
  10         32  
  10         22  
88             }
89             };
90              
91             1;
92              
93             __END__