-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add: Send user-provided data with User-ID using the Measurement Proto…
…col (#91)
- Loading branch information
Showing
5 changed files
with
321 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
|
||
namespace AlexWestergaard\PhpGa4\Helper; | ||
|
||
class CountryIsoHelper | ||
{ | ||
static public function valid(string $iso): bool | ||
{ | ||
return array_search(mb_strtoupper(trim($iso)), [ | ||
"AF", "AX", "AL", "DZ", "AS", "AD", "AO", "AI", "AQ", "AG", "AR", "AM", "AW", | ||
"AU", "AT", "AZ", "BS", "BH", "BD", "BB", "BY", "BE", "BZ", "BJ", "BM", "BT", | ||
"BO", "BA", "BW", "BV", "BR", "IO", "BN", "BG", "BF", "BI", "KH", "CM", "CA", | ||
"CV", "KY", "CF", "TD", "CL", "CN", "CX", "CC", "CO", "KM", "CG", "CD", "CK", | ||
"CR", "CI", "HR", "CU", "CY", "CZ", "DK", "DJ", "DM", "DO", "EC", "EG", "SV", | ||
"GQ", "ER", "EE", "ET", "FK", "FO", "FJ", "FI", "FR", "GF", "PF", "TF", "GA", | ||
"GM", "GE", "DE", "GH", "GI", "GR", "GL", "GD", "GP", "GU", "GT", "GG", "GN", | ||
"GW", "GY", "HT", "HM", "VA", "HN", "HK", "HU", "IS", "IN", "ID", "IR", "IQ", | ||
"IE", "IM", "IL", "IT", "JM", "JP", "JE", "JO", "KZ", "KE", "KI", "KR", "KP", | ||
"KW", "KG", "LA", "LV", "LB", "LS", "LR", "LY", "LI", "LT", "LU", "MO", "MK", | ||
"MG", "MW", "MY", "MV", "ML", "MT", "MH", "MQ", "MR", "MU", "YT", "MX", "FM", | ||
"MD", "MC", "MN", "ME", "MS", "MA", "MZ", "MM", "NA", "NR", "NP", "NL", "AN", | ||
"NC", "NZ", "NI", "NE", "NG", "NU", "NF", "MP", "NO", "OM", "PK", "PW", "PS", | ||
"PA", "PG", "PY", "PE", "PH", "PN", "PL", "PT", "PR", "QA", "RE", "RO", "RU", | ||
"RW", "BL", "SH", "KN", "LC", "MF", "PM", "VC", "WS", "SM", "ST", "SA", "SN", | ||
"RS", "SC", "SL", "SG", "SK", "SI", "SB", "SO", "ZA", "GS", "ES", "LK", "SD", | ||
"SR", "SJ", "SZ", "SE", "CH", "SY", "TW", "TJ", "TZ", "TH", "TL", "TG", "TK", | ||
"TO", "TT", "TN", "TR", "TM", "TC", "TV", "UG", "UA", "AE", "GB", "US", "UM", | ||
"UY", "UZ", "VU", "VE", "VN", "VG", "VI", "WF", "EH", "YE", "ZM", "ZW", | ||
], true) !== false; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
<?php | ||
|
||
namespace AlexWestergaard\PhpGa4\Helper; | ||
|
||
class UserDataHelper | ||
{ | ||
private ?string $sha256_email_address = null; | ||
private ?string $sha256_phone_number = null; | ||
|
||
private ?string $sha256_first_name = null; | ||
private ?string $sha256_last_name = null; | ||
private ?string $sha256_street = null; | ||
private ?string $city = null; | ||
private ?string $region = null; | ||
private ?string $postal_code = null; | ||
private ?string $country = null; | ||
|
||
public function reset(): void | ||
{ | ||
$this->sha256_email_address = null; | ||
$this->sha256_phone_number = null; | ||
$this->sha256_first_name = null; | ||
$this->sha256_last_name = null; | ||
$this->sha256_street = null; | ||
$this->city = null; | ||
$this->region = null; | ||
$this->postal_code = null; | ||
$this->country = null; | ||
} | ||
|
||
/** | ||
* @param string $email | ||
* @return bool | ||
*/ | ||
public function setEmail(string $email): bool | ||
{ | ||
$email = str_replace(" ", "", mb_strtolower($email)); | ||
if (!filter_var($email, FILTER_VALIDATE_EMAIL)) return false; | ||
|
||
// https://support.google.com/mail/answer/7436150 | ||
if ( | ||
substr($email, -mb_strlen("@gmail.com")) == "@gmail.com" || | ||
substr($email, -mb_strlen("@googlemail.com")) == "@googlemail.com" | ||
) { | ||
[$addr, $host] = explode("@", $email, 2); | ||
// https://support.google.com/mail/thread/125577450/gmail-and-googlemail | ||
if ($host == "googlemail.com") { | ||
$host = "gmail.com"; | ||
} | ||
// https://gmail.googleblog.com/2008/03/2-hidden-ways-to-get-more-from-your.html | ||
$addr = explode("+", $addr, 2)[0]; | ||
$addr = str_replace(".", "", $addr); | ||
$email = implode("@", [trim($addr), trim($host)]); | ||
} | ||
|
||
$this->sha256_email_address = hash("sha256", $email); | ||
return true; | ||
} | ||
|
||
/** | ||
* @param int $number International number (without prefix "+" and dashes) eg. \ | ||
* "+1-123-4567890" for USA or\ | ||
* "+44-1234-5678900" for UK or\ | ||
* "+45-12345678" for DK | ||
* @return bool | ||
*/ | ||
public function setPhone(int $number): bool | ||
{ | ||
$sNumber = strval($number); | ||
if (strlen($sNumber) < 3 || strlen($sNumber) > 15) { | ||
return false; | ||
} | ||
|
||
$this->sha256_phone_number = hash("sha256", "+{$sNumber}"); | ||
return true; | ||
} | ||
|
||
/** | ||
* @param string $firstName Users first name | ||
* @return bool | ||
*/ | ||
public function setFirstName(string $firstName): bool | ||
{ | ||
if (empty($firstName)) return false; | ||
$this->sha256_first_name = hash("sha256", $this->strip($firstName, true)); | ||
return true; | ||
} | ||
|
||
/** | ||
* @param string $lastName Users last name | ||
* @return bool | ||
*/ | ||
public function setLastName(string $lastName): bool | ||
{ | ||
if (empty($lastName)) return false; | ||
$this->sha256_last_name = hash("sha256", $this->strip($lastName, true)); | ||
return true; | ||
} | ||
|
||
/** | ||
* @param string $street Users street name | ||
* @return bool | ||
*/ | ||
public function setStreet(string $street): bool | ||
{ | ||
if (empty($street)) return false; | ||
$this->sha256_street = hash("sha256", $this->strip($street)); | ||
return true; | ||
} | ||
|
||
/** | ||
* @param string $city Users city name | ||
* @return bool | ||
*/ | ||
public function setCity(string $city): bool | ||
{ | ||
if (empty($city)) return false; | ||
$this->city = $this->strip($city, true); | ||
return true; | ||
} | ||
|
||
/** | ||
* @param string $region Users region name | ||
* @return bool | ||
*/ | ||
public function setRegion(string $region): bool | ||
{ | ||
if (empty($region)) return false; | ||
$this->region = $this->strip($region, true); | ||
return true; | ||
} | ||
|
||
/** | ||
* @param string $postalCode Users postal code | ||
* @return bool | ||
*/ | ||
public function setPostalCode(string $postalCode): bool | ||
{ | ||
if (empty($postalCode)) return false; | ||
$this->postal_code = $this->strip($postalCode); | ||
return true; | ||
} | ||
|
||
/** | ||
* @param string $iso Users country (ISO) | ||
* @return bool | ||
*/ | ||
public function setCountry(string $iso): bool | ||
{ | ||
if (!CountryIsoHelper::valid($iso)) { | ||
return false; | ||
} | ||
|
||
$this->country = mb_strtoupper(trim($iso)); | ||
return true; | ||
} | ||
|
||
public function toArray(): array | ||
{ | ||
$res = []; | ||
|
||
if (!empty($this->sha256_email_address)) { | ||
$res["sha256_email_address"] = $this->sha256_email_address; | ||
} | ||
|
||
if (!empty($this->sha256_phone_number)) { | ||
$res["sha256_phone_number"] = $this->sha256_phone_number; | ||
} | ||
|
||
$addr = []; | ||
|
||
if (!empty($this->sha256_first_name)) { | ||
$addr["sha256_first_name"] = $this->sha256_first_name; | ||
} | ||
|
||
if (!empty($this->sha256_last_name)) { | ||
$addr["sha256_last_name"] = $this->sha256_last_name; | ||
} | ||
|
||
if (!empty($this->sha256_street)) { | ||
$addr["sha256_street"] = $this->sha256_street; | ||
} | ||
|
||
if (!empty($this->city)) { | ||
$addr["city"] = $this->city; | ||
} | ||
|
||
if (!empty($this->region)) { | ||
$addr["region"] = $this->region; | ||
} | ||
|
||
if (!empty($this->postal_code)) { | ||
$addr["postal_code"] = $this->postal_code; | ||
} | ||
|
||
if (!empty($this->country)) { | ||
$addr["country"] = $this->country; | ||
} | ||
|
||
if (!empty($this->sha256_phone_number)) { | ||
$res["sha256_phone_number"] = $this->sha256_phone_number; | ||
} | ||
|
||
if (count($addr) > 0) { | ||
$res["address"] = $addr; | ||
} | ||
|
||
return $res; | ||
} | ||
|
||
private function strip(string $s, bool $removeDigits = false): string | ||
{ | ||
$d = $removeDigits ? '0-9' : ''; | ||
|
||
$s = preg_replace("[^a-zA-Z{$d}\-\_\.\,\s]", "", $s); | ||
$s = mb_strtolower($s); | ||
return trim($s); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
<?php | ||
|
||
namespace AlexWestergaard\PhpGa4Test\Unit; | ||
|
||
use AlexWestergaard\PhpGa4\Event\Login; | ||
use AlexWestergaard\PhpGa4\Helper\UserDataHelper; | ||
use AlexWestergaard\PhpGa4Test\TestCase; | ||
|
||
final class UserDataTest extends TestCase | ||
{ | ||
public function test_user_data_is_fillable() | ||
{ | ||
$uda = new UserDataHelper(); | ||
$this->assertTrue($uda->setEmail($setEmail = "[email protected]")); | ||
$this->assertTrue($uda->setPhone($setPhone = 4500000000)); | ||
$this->assertTrue($uda->setFirstName($setFirstName = "test")); | ||
$this->assertTrue($uda->setLastName($setLastName = "person")); | ||
$this->assertTrue($uda->setStreet($setStreet = "some street 11")); | ||
$this->assertTrue($uda->setCity($setCity = "somewhere")); | ||
$this->assertTrue($uda->setRegion($setRegion = "inthere")); | ||
$this->assertTrue($uda->setPostalCode($setPostalCode = "1234")); | ||
$this->assertTrue($uda->setCountry($setCountry = "DK")); | ||
|
||
$export = $uda->toArray(); | ||
$this->assertIsArray($export); | ||
$this->assertEquals(hash("sha256", $setEmail), $export["sha256_email_address"], $setEmail); | ||
$this->assertEquals(hash("sha256", '+' . $setPhone), $export["sha256_phone_number"], $setPhone); | ||
|
||
$this->assertArrayHasKey("address", $export); | ||
$this->assertIsArray($export["address"]); | ||
$this->assertEquals(hash("sha256", $setFirstName), $export["address"]["sha256_first_name"], $setFirstName); | ||
$this->assertEquals(hash("sha256", $setLastName), $export["address"]["sha256_last_name"], $setLastName); | ||
$this->assertEquals(hash("sha256", $setStreet), $export["address"]["sha256_street"], $setStreet); | ||
$this->assertEquals($setCity, $export["address"]["city"], $setCity); | ||
$this->assertEquals($setRegion, $export["address"]["region"], $setRegion); | ||
$this->assertEquals($setPostalCode, $export["address"]["postal_code"], $setPostalCode); | ||
$this->assertEquals($setCountry, $export["address"]["country"], $setCountry); | ||
} | ||
public function test_user_data_is_sendable() | ||
{ | ||
$uad = $this->analytics->userdata(); | ||
$uad->setEmail("[email protected]"); | ||
$uad->setPhone(4500000000); | ||
$uad->setFirstName("test"); | ||
$uad->setLastName("person"); | ||
$uad->setStreet("some street 11"); | ||
$uad->setCity("somewhere"); | ||
$uad->setRegion("inthere"); | ||
$uad->setPostalCode("1234"); | ||
$uad->setCountry("DK"); | ||
|
||
$this->analytics->addEvent(Login::new()); | ||
$this->assertNull($this->analytics->post()); | ||
} | ||
} |