From cdbcbbab5ddd0931d104434c2c8ee07b494a2a7b Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Wed, 17 Jun 2026 18:20:36 +0200 Subject: [PATCH 1/2] fix: support groups key for capture events --- .changeset/great-groups-capture.md | 5 +++ lib/Client.php | 5 +++ test/PostHogTest.php | 49 ++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 .changeset/great-groups-capture.md diff --git a/.changeset/great-groups-capture.md b/.changeset/great-groups-capture.md new file mode 100644 index 0000000..7195743 --- /dev/null +++ b/.changeset/great-groups-capture.md @@ -0,0 +1,5 @@ +--- +"posthog-php": patch +--- + +Copy capture `groups` input to the `$groups` event property so grouped events are associated correctly. diff --git a/lib/Client.php b/lib/Client.php index ba2c8ab..eb3729d 100644 --- a/lib/Client.php +++ b/lib/Client.php @@ -216,6 +216,7 @@ public function capture(array $message) { $flagsSnapshot = $message["flags"] ?? null; unset($message["flags"]); + $hasGroups = array_key_exists("groups", $message); $usedGeneratedPersonlessDistinctId = false; if ($this->shouldApplyCaptureContext($message)) { @@ -224,6 +225,10 @@ public function capture(array $message) $message = $this->message($message); $message["type"] = "capture"; + if (!array_key_exists('$groups', $message) && $hasGroups) { + $message['$groups'] = $message['groups']; + } + if (array_key_exists('$groups', $message)) { $message["properties"]['$groups'] = $message['$groups']; } diff --git a/test/PostHogTest.php b/test/PostHogTest.php index 130f5d4..3cb9e18 100644 --- a/test/PostHogTest.php +++ b/test/PostHogTest.php @@ -55,6 +55,18 @@ private function getConsumer(Client $client): object return $consumerProp->getValue($client); } + private function firstBatchEvent(): array + { + foreach ($this->http_client->calls as $call) { + if (($call["path"] ?? null) === "/batch/") { + $decoded = json_decode($call["payload"], true); + return $decoded["batch"][0]; + } + } + + self::fail("Expected a /batch/ call to have been made"); + } + private function withEnvApiKey(?string $apiKey, callable $callback): void { $previousApiKey = getenv(PostHog::ENV_API_KEY); @@ -448,6 +460,43 @@ public function testCapture(): void ); } + public function testCaptureCopiesGroupsKeyToDollarGroupsProperty(): void + { + self::assertTrue( + PostHog::capture( + array( + "distinctId" => "john", + "event" => "grouped event", + "groups" => array("team" => 1), + ) + ) + ); + PostHog::flush(); + + $event = $this->firstBatchEvent(); + + self::assertSame(array("team" => 1), $event["properties"]['$groups']); + self::assertSame(array("team" => 1), $event["groups"]); + } + + public function testCaptureKeepsDollarGroupsCompatibility(): void + { + self::assertTrue( + PostHog::capture( + array( + "distinctId" => "john", + "event" => "grouped event", + '$groups' => array("team" => 1), + ) + ) + ); + PostHog::flush(); + + $event = $this->firstBatchEvent(); + + self::assertSame(array("team" => 1), $event["properties"]['$groups']); + } + public function testCaptureIncludesIsServerProperty(): void { self::assertTrue( From 2d8529a9cd903734c4e070a7b9df64c6fe01c272 Mon Sep 17 00:00:00 2001 From: Manoel Aranda Neto Date: Wed, 17 Jun 2026 19:01:56 +0200 Subject: [PATCH 2/2] test: parameterize capture groups coverage --- test/PostHogTest.php | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/test/PostHogTest.php b/test/PostHogTest.php index 3cb9e18..664c324 100644 --- a/test/PostHogTest.php +++ b/test/PostHogTest.php @@ -105,6 +105,14 @@ public static function initNoOpApiKeyCases(): array ]; } + public static function captureGroupsCases(): array + { + return [ + 'groups key' => ["groups"], + '$groups key' => ['$groups'], + ]; + } + public static function disabledClientNoRequestCases(): array { return [ @@ -460,33 +468,17 @@ public function testCapture(): void ); } - public function testCaptureCopiesGroupsKeyToDollarGroupsProperty(): void - { - self::assertTrue( - PostHog::capture( - array( - "distinctId" => "john", - "event" => "grouped event", - "groups" => array("team" => 1), - ) - ) - ); - PostHog::flush(); - - $event = $this->firstBatchEvent(); - - self::assertSame(array("team" => 1), $event["properties"]['$groups']); - self::assertSame(array("team" => 1), $event["groups"]); - } - - public function testCaptureKeepsDollarGroupsCompatibility(): void + /** + * @dataProvider captureGroupsCases + */ + public function testCaptureAddsGroupsProperty(string $groupsKey): void { self::assertTrue( PostHog::capture( array( "distinctId" => "john", "event" => "grouped event", - '$groups' => array("team" => 1), + $groupsKey => array("team" => 1), ) ) );