File Coverage

blib/lib/Net/Google/Analytics/MeasurementProtocol.pm
Criterion Covered Total %
statement 20 56 35.7
branch 0 22 0.0
condition 0 32 0.0
subroutine 4 8 50.0
pod 2 2 100.0
total 26 120 21.6


line stmt bran cond sub pod time code
1             package Net::Google::Analytics::MeasurementProtocol;
2 3     3   40228 use strict;
  3         4  
  3         71  
3 3     3   9 use warnings;
  3         4  
  3         59  
4 3     3   8 use Carp ();
  3         8  
  3         1637  
5              
6             our $VERSION = 0.04;
7              
8             sub new {
9 0     0 1 0 my $class = shift;
10 0 0       0 my %args = (@_ == 1 ? %{$_[0]} : @_ );
  0         0  
11              
12             Carp::croak 'tracking_id (tid) missing or invalid'
13 0 0 0     0 unless $args{tid} && $args{tid} =~ /^(?:UA|MO|YT)-\d+-\d+$/;
14              
15             # If the 'aip' key exists, even if set to 0, the ip will be anonymized.
16             # So we only push it to our args if user set it to 1.
17 0 0 0     0 delete $args{aip} if exists $args{aip} && !$args{aip};
18              
19             # default settings:
20 0   0     0 $args{ua} ||= __PACKAGE__ . "/$VERSION";
21 0   0     0 $args{cid} ||= _gen_uuid_v4();
22 0   0     0 $args{v} ||= 1;
23 0   0     0 $args{cd} ||= '/';
24 0   0     0 $args{an} ||= 'My App';
25 0   0     0 $args{ds} ||= 'app';
26              
27 0   0     0 my $ua_object = $args{ua_object} || _build_user_agent( $args{ua} );
28 0 0 0     0 unless ( $ua_object->isa('Furl') || $ua_object->isa('LWP::UserAgent') ) {
29 0         0 Carp::croak('ua_object must be of type Furl or LWP::UserAgent');
30             }
31              
32 0         0 my $debug = delete $args{debug};
33 0         0 return bless {
34             args => \%args,
35             debug => $debug,
36             ua => $ua_object,
37             }, $class;
38             }
39              
40             sub send {
41 0     0 1 0 my ($self, $hit_type, $args) = @_;
42              
43 0         0 my %args = (%{$self->{args}}, %$args, t => $hit_type);
  0         0  
44 0         0 my %required = (
45             pageview => [qw(v tid cid cd an)],
46             screenview => [qw(v tid cid cd an)],
47             event => [qw(v tid cid cd an ec ea)],
48             transaction => [qw(v tid cid cd an ti)],
49             item => [qw(v tid cid cd an ti in)],
50             social => [qw(v tid cid cd an sn sa st)],
51             exception => [qw(v tid cid cd an)],
52             timing => [qw(v tid cid cd an utc utv utt)],
53             );
54 0 0       0 Carp::croak("invalid hit type $hit_type") unless $required{$hit_type};
55              
56 0         0 foreach my $required ( @{$required{$hit_type}} ) {
  0         0  
57             Carp::croak("argument '$required' is required for '$hit_type' hit type. See https://developers.google.com/analytics/devguides/collection/protocol/v1/parameters#$required for more information")
58 0 0       0 unless $args{$required};
59             }
60             Carp::croak('for "pageview" hit types you must set either "dl" or both "dh" and "dp"')
61 0 0 0     0 if $hit_type eq 'pageview' && !($args{dl} || ($args{dh} && $args{dp}));
      0        
62              
63 0         0 return $self->_request(\%args);
64             }
65              
66             sub _request {
67 0     0   0 my ($self, $args) = @_;
68              
69 0         0 my $ua = $self->{ua};
70             my $target = $self->{debug}
71 0 0       0 ? 'https://www.google-analytics.com/debug/collect'
72             : 'https://www.google-analytics.com/collect'
73             ;
74              
75             # Compatibility layer for LWP::UserAgent
76 0 0       0 my $res = $ua->post( $target, $ua->isa('Furl') ? undef : (), $args );
77 0 0       0 if ($self->{debug}) {
78 0         0 return $res;
79             }
80             else {
81 0 0       0 return $self->{debug} ? $res : $res->is_success;
82             }
83             }
84              
85             sub _build_user_agent {
86 0     0   0 my ($ua) = @_;
87 0         0 require Furl;
88 0         0 return Furl->new( agent => $ua, timeout => 5 );
89             }
90              
91             # UUID v4 (pseudo-random) generator based on UUID::Tiny
92             sub _gen_uuid_v4 {
93 2     2   9 my $uuid = '';
94 2         6 for ( 1 .. 4 ) {
95 8         10 my $v1 = int(rand(65536)) % 65536;
96 8         6 my $v2 = int(rand(65536)) % 65536;
97 8         8 my $rand_32bit = ($v1 << 16) | $v2;
98 8         12 $uuid .= pack 'I', $rand_32bit;
99             }
100 2         6 substr $uuid, 6, 1, chr( ord( substr( $uuid, 6, 1 ) ) & 0x0f | 0x40 );
101 2         4 substr $uuid, 8, 1, chr( ord( substr( $uuid, 8, 1 ) ) & 0x3f | 0x80 );
102              
103             # uuid is created. Convert to string:
104             return join '-',
105 10         22 map { unpack 'H*', $_ }
106 2         4 map { substr $uuid, 0, $_, '' }
  10         12  
107             ( 4, 2, 2, 2, 6 );
108             }
109              
110             1;
111             __END__