Skip to content

Commit f0951cd

Browse files
authored
Add helper to parse Session ID from different GA versions (#108)
* add parseSessionCookie helper method This helper parses the `_GA_{ga_id}` session cookie (both GS1 & GS2 formats) into an associative array of data. * add tests for praseing session cookies
1 parent db19964 commit f0951cd

2 files changed

Lines changed: 115 additions & 3 deletions

File tree

src/Helper/ConvertHelper.php

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
namespace AlexWestergaard\PhpGa4\Helper;
44

5-
use AlexWestergaard\PhpGa4\Facade\Type\EventType;
65
use AlexWestergaard\PhpGa4\Exception\Ga4Exception;
6+
use AlexWestergaard\PhpGa4\Facade\Type\EventType;
77

88
class ConvertHelper
99
{
@@ -77,4 +77,68 @@ public static function parseEvents(array $list): array
7777
}
7878
return $events;
7979
}
80+
81+
/**
82+
* Parse the session cookie (GA_{measurement_id}) into named parts.
83+
*
84+
* @param string $session The cookie value
85+
* @return array
86+
*/
87+
public static function parseSessionCookie(string $session): array
88+
{
89+
$parts = explode('.', $session);
90+
91+
$version = $parts[0] ?? null;
92+
$k = $parts[1] ?? null;
93+
$data = $parts[2] ?? null;
94+
95+
// If the data part is empty, return an empty array
96+
if (!$data) {
97+
return [];
98+
}
99+
100+
if ($version === 'GS1') {
101+
$data = explode('.', $session);
102+
103+
return [
104+
'version' => $data[0] ?? null,
105+
'domain_level' => $data[1] ?? null,
106+
'session_id' => $data[2] ?? null,
107+
'session_number' => $data[3] ?? null,
108+
'session_engagement' => $data[4] ?? null,
109+
'timestampt' => $data[5] ?? null
110+
];
111+
}
112+
113+
$cookieParts = explode('$', $data);
114+
115+
if (empty(array_filter($cookieParts))) {
116+
return [];
117+
}
118+
119+
$data = array_map(
120+
fn ($part) => match ($part[0]) {
121+
's' => ['session_id' => $part],
122+
't' => ['timestamp' => $part],
123+
'o' => ['session_number' => $part],
124+
'g' => ['session_engaged' => $part],
125+
'j' => ['join_timer' => $part],
126+
'l' => ['logged_in_state' => $part],
127+
'h' => ['user_id' => $part],
128+
'd' => ['join_id' => $part],
129+
default => [$part[0] => $part]
130+
},
131+
$cookieParts
132+
);
133+
134+
$result = [];
135+
136+
foreach ($data as $mapValue) {
137+
foreach ($mapValue as $key => $value) {
138+
$result[$key] = $value;
139+
}
140+
}
141+
142+
return $result;
143+
}
80144
}

test/Unit/HelperTest.php

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
namespace AlexWestergaard\PhpGa4Test\Unit;
44

5-
use AlexWestergaard\PhpGa4\Helper;
6-
use AlexWestergaard\PhpGa4\Facade;
75
use AlexWestergaard\PhpGa4\Event;
6+
use AlexWestergaard\PhpGa4\Facade;
7+
use AlexWestergaard\PhpGa4\Helper;
88
use AlexWestergaard\PhpGa4Test\MeasurementTestCase;
99

1010
final class HelperTest extends MeasurementTestCase
@@ -82,4 +82,52 @@ public function test_timeasmicro_throws_too_large()
8282

8383
$this->analytics->setTimestampMicros($time);
8484
}
85+
86+
public function test_parse_session_cookie_gs1()
87+
{
88+
$sessionData = Helper\ConvertHelper::parseSessionCookie('GS1.1.1689053763.1.1.1689054101.0.0.0');
89+
$this->assertEquals([
90+
'version' => 'GS1',
91+
'domain_level' => '1',
92+
'session_id' => '1689053763',
93+
'session_number' => '1',
94+
'session_engagement' => '1',
95+
'timestampt' => '1689054101',
96+
], $sessionData);
97+
}
98+
99+
public function test_parse_session_cookie_gs2()
100+
{
101+
$sessionData = Helper\ConvertHelper::parseSessionCookie('GS2.1.s1764888982$o50$g1$t1764890260$j59$l0$h681028196');
102+
$this->assertEquals([
103+
'session_id' => 's1764888982',
104+
'session_number' => 'o50',
105+
'session_engaged' => 'g1',
106+
'timestamp' => 't1764890260',
107+
'join_timer' => 'j59',
108+
'logged_in_state' => 'l0',
109+
'user_id' => 'h681028196',
110+
], $sessionData);
111+
112+
// same data, different order
113+
$sessionData = Helper\ConvertHelper::parseSessionCookie('GS2.1.t1764890260$o50$g1$s1764888982$j59$l0$h681028196');
114+
$this->assertEquals([
115+
'session_id' => 's1764888982',
116+
'session_number' => 'o50',
117+
'session_engaged' => 'g1',
118+
'timestamp' => 't1764890260',
119+
'join_timer' => 'j59',
120+
'logged_in_state' => 'l0',
121+
'user_id' => 'h681028196',
122+
], $sessionData);
123+
}
124+
125+
public function test_parse_session_cookie_invalid()
126+
{
127+
$sessionData = Helper\ConvertHelper::parseSessionCookie('invalid');
128+
$this->assertEquals([], $sessionData);
129+
130+
$sessionData = Helper\ConvertHelper::parseSessionCookie('');
131+
$this->assertEquals([], $sessionData);
132+
}
85133
}

0 commit comments

Comments
 (0)