zumba / amplitude-php
Amplitude的PHP SDK
Requires (Dev)
- php-coveralls/php-coveralls: ^2.4
- phpunit/phpunit: 8.3.* | ^9
- squizlabs/php_codesniffer: 3.4.*
README
这是一个相对简洁的PHP API,用于Amplitude,功能强大,能满足你的需求,同时不会造成干扰。设计用于以下两种主要场景
- 使用相同用户和Amplitude应用的多个事件 - 当你需要跟踪同一用户可能发生的多个事件,且所有事件都属于同一Amplitude应用时。这个库提供了一个单例实例,允许在页面加载时初始化API密钥和用户信息,该信息在页面加载期间用于记录任何事件。
- 多个用户和可能多个Amplitude应用的多个事件 - 当你需要为许多不同的用户记录多个事件,可能使用不同的amplitude应用时。
示例
// After User is Initialized in your application, set the user info in Amplitude that you want to track (minimally // the user identifier or device identifier, and of course your Amplitude App API key) $amplitude = \Zumba\Amplitude\Amplitude::getInstance(); $amplitude->init('APIKEY', 'johnny@example.com') ->setUserProperties([ 'dob' => '1980-11-04', 'name' => 'Johnny 5' ]) // Only call this once API Key and user ID or device ID is set ->logQueuedEvents(); // -- Meanwhile, in another part of the code... -- // Anywhere else in your application that needs to log an event // This will even work if called before the above code initializes Amplitude! If that is case, it will queue it // and send the event when logQueuedEvents() is called. If Amplitude is already initialized, this will send the event // to Amplitude right away (only uses a queue for early-logged events) \Zumba\Amplitude\Amplitude::getInstance() ->queueEvent('EVENT TYPE'); // Can pass in an array for the second parameter to set event properties \Zumba\Amplitude\Amplitude::getInstance() ->queueEvent('SECOND EVENT', ['quantity' => 1, 'price' => 15.32, 'Custom Property' => 'Widgets']); // This is a simple example to get you started, see the rest of the readme for more examples
入门指南 & 故障排除
当你首次设置应用程序时,如果你的事件没有出现在Amplitude中,你可能需要进行一些故障排除。通常,“它工作”的迹象是当你在Amplitude应用中首次看到你的事件时。
如果你从未看到那个第一个事件出现,你可以查看当事件记录时Amplitude的响应。这可能会帮助你找到并解决问题(例如无效的API密钥、PHP环境错误、连接问题等)
Amplitude使用Psr\Logger
来记录与Amplitude HTTP API的通信。你可以通过设置记录器(使用$amlitude->setLogger()
)来利用这一点,以帮助捕获任何问题。
独立的故障排除脚本
以下是一个独立的脚本,打算复制到应用程序文档根目录下的PHP文件中。只需更改APIKEY
,如有必要,调整需要autoload.php
文件的行。然后从浏览器访问脚本的URL,查看记录的消息。
<?php // Stand-alone Amplitude troubleshooting script - just change APIKEY in next line $apikey = 'APIKEY'; // Composer Autoloader - If new to composer, see https://getcomposer.org.cn require __DIR__ . '/vendor/autoload.php'; // Make sure if there is some error, we will see it ini_set('display_errors', true); error_reporting(E_ALL); // Quick logger to display log messages - NOT for production use, this displays log message to the browser class ChattyLogger extends \Psr\Log\AbstractLogger { public function log($level, $message, array $context = []) { echo "<p><strong>".ucfirst($level).":</strong> $message<br>"; if (!empty($context)) { echo '<strong>Context:</strong><br><span class="code">'.print_r($context,true).'</span>'; } echo '</p>'; } } $chatty = new ChattyLogger(); // Test logging an event ?> <style> .code { display: inline-block; border: 1px solid #a7a7a7; padding: 15px; margin: 0 5px; background-color: #eaeaea; white-space: pre; } p { padding-bottom: 5px; border-bottom: thin dashed gray; } </style> <h1>Testing Amplitude Log Event Response</h1> <h2>API Key: '<?= $apikey ?>'</h2> <?php $amplitude = new \Zumba\Amplitude\Amplitude(); // Add the chatty logger so we can see log messages $amplitude->setLogger($chatty); // Initialize Amplitude with the API key and a dummy test user ID $amplitude->init($apikey, 'TEST-USER-ID'); $chatty->info('Calling $amplitude->logEvent(\'TEST EVENT\')...'); // Log a test event $amplitude->logEvent('TEST EVENT'); $chatty->info('Done logging event');
故障排除技巧
- Amplitude库会对由代码中的错误引起的问题抛出
LogicException
,例如如果你尝试记录事件而没有首先设置API密钥,或者尝试记录没有指定事件类型的事件。确保你的服务器错误日志设置已设置以显示(或以其他方式记录)可能抛出的任何异常,这样你就可以看到是否有编码错误导致问题。 - 确保PHP错误日志已启用(或显示错误已启用),这样你就可以看到可能指向问题的任何PHP错误。
- 使用Amplitude中的
setLogger(...)
方法使用你的应用程序日志或如上面的独立测试脚本中自己的自定义记录器。只要它实现了Psr\Log\LoggerInterface
。- 如果没有生成日志:它没有尝试在应用程序记录器设置后发送事件,或者事件使用没有设置记录器的不同实例记录。
- 如果你看到记录了
Curl错误:
,那么在尝试发送请求时出了问题,错误消息和上下文应该有助于指向问题。 - 如果没有curl错误,它将记录以
Amplitude HTTP API响应:
开头的信息。success
withhttpCode = 200
:Amplitude 已收到请求,事件应已记录。如果您在 Amplitude 中看不到它,请过几分钟后再检查,有时 Amplitude 可能会稍微滞后。- 其他情况:事件未能成功记录,请参考消息和上下文以帮助排除问题。
匿名用户记录
由于这是一个 PHP SDK,有很多选项可以跟踪匿名用户。由于这可以在 CLI 模式下运行或作为 cron 作业运行,此 SDK 不为您处理会话。
您的应用程序需要找出一种方法来跟踪跨多个页面加载的用户,您的应用程序可能已经使用 PHP 会话或类似的方法来做这件事。
一旦您有了允许匿名用户在页面加载之间被跟踪的唯一标识符,将其设置为 deviceId
。对于已登录用户和匿名用户都这样做,这样一旦用户登录,他们过去的活动就会被链接到用户。
// After your application has set up the session (for instance in your bootloader or similar), initialize Amplitude: $amplitude = \Zumba\Amplitude\Amplitude::getInstance(); // Notice we are not setting second parameter here for user ID, we will do that below if it is available $amplitude->init('APIKEY'); // Can use the PHP session ID, or alternatively, any unique string your application uses to track sessions $sessionId = session_id(); // Keep track of whether we have a session or user ID $canLogEvents = false; if (!empty($sessionId)) { $amplitude->setDeviceId($sessionId); $canLogEvents = true; } // Presumes $applicationUserId set prior to this by your application if (!empty($applicationUserId)) { $amplitude->setUserId($applicationUserId); $canLogEvents = true; } if (!empty($userData)) { // If you have other user properties, set them as well... They will be set on the first event sent to Amplitude $amplitude->setUserProperties($userData); } if ($canLogEvents) { // Make sure to send any events that may have gotten queued early $amplitude->logQueuedEvents(); } else { // Do not have a user ID or device ID for this page load, so set `optOut`, to prevent amplitude from trying // to send events (since it won't work without user or device ID) $amplitude->setOptOut(true); } // -- Meanwhile, in another part of the code... -- // Just queue events as normal \Zumba\Amplitude\Amplitude::getInstance()->queueEvent('EVENT');
用户属性
设置用户属性主要有一种方法,这将使用户属性与下一个发送到 Amplitude 的 Amplitude 事件一起发送。
\Zumba\Amplitude\Amplitude::getInstance() ->setUserProperties( [ 'name' => 'Jane', 'dob' => $dob, // ... ] );
通常在调用 logQueuedEvents()
之前调用此方法,以确保它随第一个排队的事件(如果有)一起发送。
使用此方法,它仅与一个事件一起发送用户信息,因为一旦在 Amplitude 中设置了用户属性,它就会持续匹配用户 ID 或事件 ID 的所有事件。
请注意,如果在发送 setUserProperties()
之后没有发送任何事件,则这些属性不会发送到 Amplitude。
一种选择是使用登录事件,在用户登录时添加用户信息,并将其发送在登录事件中。这样,您只为用户登录的页面加载发送用户属性。
或者,在初始化 Amplitude 对象时,每次页面加载都添加用户属性。这是示例中使用的选项。
在事件对象上添加用户属性
设置用户属性的另一种选择是在事件对象本身上设置它们。您可以通过设置/更改 userProperties
或使用 Event
对象上的 setUserProperties()
方法来实现。
通常在类似于下一节中的情况下使用此方法,在您可能在同一页面加载中为不同用户发送事件时。
$event = new \Zumba\Amplitude\Event(); // Method 1 - set user properties method: $event->setUserProperties( [ 'name' => 'Rambo', // ... ] ); // If you called setUserProperties() a second time, it would overwrite any properties with the same name but leave // others intact // Method 2 - just set the userProperties directly: $event->userProperties = [ 'name' => 'Mary', // ... ]; // This works just like you would expect: it will reset what is already there. // Note that prior to anything being set, $event->userProperties will be null, not an empty array
有关事件对象如何工作的更多信息,请参阅下面的 事件 部分。
用例:为许多用户发送事件
在您将发送许多针对不同用户的 Amplitude 事件的情况下,您实际上可以在事件对象上添加用户属性,就像我们在上一节中介绍的那样。事实上,除了 API 密钥之外,一切都可以在事件对象上设置。
例如
// Here, we are not using Singleton as we will only use this connection to send these batch user events, we don't // want any user data from the Singleton instance to accidentally bleed into the first user's event $amplitude = new \Zumba\Amplitude\Amlitude(); // Alternatively, if we wanted to re-use the same Amplitude object with the same key elsewhere in the code, could // have used: // $amplitude = \Zumba\Amplitude\Amplitude::getInstance('NAMED-INSTANCE'); // That will maintain the same Amplitude instance anywhere that requests that specific name. $amplitude->init('APIKEY'); // $userEvents might be an array your application generates with user info and events that need to be sent foreach ($userEvents as $myUserEvent) { $event = $amplitude->event(); // Notice below we are setting user ID and user data on the event itself, not inside Amplitude where it would end // up persisting the user ID between logged events... // The below assumes an array set like so: /* $myUserEvent = [ 'id' => 'user-id', 'user_details' => [], // key/value array of user info 'event_type' => 'EVENT', // event to log 'event_properties' => [], // key/value array of event properties to set ]; */ $event->userId = $myUserEvent['id']; $event->userProperties = $myUserEvent['user_details']; $event->eventType = $myUserEvent['event_type']; $event->set($myUserEvent['event_properties']); // Since we used $amplitude->event() to get event object, it will be the event to be sent when we call this $amplitude->logEvent(); // Above we are using logEvent instead of queueEvent since the code is not "spread out", we can ensure that // amplitude is already initialized and all the requirements (eventType and either userId or deviceId) are set // on the event already }
有关如何使用 Event
对象的更多详细信息,请参阅下一节。
事件
这个库在如何设置要发送到 Amplitude 的事件方面非常灵活。使用最适合您个人偏好和项目需求的方法。
直接发送!
第一个选项是最简单的,在主示例中使用。只需调用 queueEvent
或 logEvent
并传递事件类型和事件属性(如果有)。
// Send just event with no event properties: \Zumba\Amplitude\Amplitude::getInstance() ->queueEvent('EVENT-NAME'); // Send event and add a property: \Zumba\Amplitude\Amplitude::getInstance() ->queueEvent('EVENT-NAME', ['property1' => 'value1']);
使用事件对象
您有使用事件对象设置事件的选项,如果这对您的用例更方便,下面的示例是如何做到这一点的。
// Get the next event that will be queued or sent: $event = \Zumba\Amplitude\Amplitude::getInstance()->event(); // Set up the event here, by setting properties... $event->eventType = 'EVENT-NAME'; // Queue or send the event - since we got the event using the event method, it will be the one used on the next // queue or send, no need to pass it back in. \Zumba\Amplitude\Amplitude::getInstance()->queueEvent();
设置事件属性
至于在事件对象上设置事件属性,一旦你有了那个 $event
对象,你就有几种选择。
// First, probably the most common, you can use the magic set methods to just set the property like this: $event->propertyName = 'property value'; // Set using set(), handy for property names that are invalid as PHP variables: $event->set('Property name with Space', 'property value'); // Set can be chained: $event->set('prop1', 'val1') ->set('prop2', 'val2') ->set('prop3', 'val3'); // Pass in array of properties for the first parameter: $event->set( [ 'prop1' => 'val1', 'prop2' => 'val2', ] );
取消设置事件属性
如果一个属性已经在事件上被设置了,你可以取消它。
// For non-standard property names, use the unsetProperty method: $event->unsetProperty('My Location'); // Magic unset also works unset($event->productId);
发送或队列事件
一旦你设置了所有事件属性,你就可以通过调用 $amplitude->queueEvent()
或 $amplitude->logEvent()
来发送或队列事件。
注意:如果你刚刚创建了一个新的 Event
对象,在调用 queueEvent()
或 logEvent()
之前,你必须像这样将事件传递给 Amplitude
$event = new \Zumba\Amplitude\Event(); // Set event properties here // Pass the event into amplitude and queue it \Zumba\Amplitude\Amplitude::getInstance() ->event($event) ->queueEvent();
然而,如果你使用事件方法获取事件,则不需要将其传递回 Amplitude。
$event = \Zumba\Amplitude\Amplitude::getInstance()->event(); // Set event properties here // Send that event \Zumba\Amplitude\Amplitude::getInstance()->queueEvent();
换句话说,当你直接处理 Event
对象时,它必须以某种方式通过 Amplitude 的 event()
方法,在尝试调用 queueEvent()
或 logEvent()
之前。
提示:无需传递事件对象
如果你需要在代码的不同部分设置事件,你可以 选择 传递该事件,但你不必这样做,因为 Amplitude
会跟踪下一个要发送或队列的事件对象。所以你可以这样做
$event = \Zumba\Amplitude\Amplitude::getInstance()->event(); $event->eventType = 'Complicated Event'; // -- Meanwhile, in another part of the code... -- // As long as the event has not yet been sent or queued up, you can get it and change it as needed: $event = \Zumba\Amplitude\Amplitude::getInstance()->event(); $event->deviceId = 'DEVICE ID'; // Just remember, once finished setting up the event, call queueEvent() or logEvent() once. \Zumba\Amplitude\Amplitude::getInstance()->queueEvent();
别忘了 eventType
当使用事件对象时,请记住,在事件队列或记录之前,必须以某种方式设置 eventType
。
// Either set it this way: $event->eventType = 'EVENT'; // OR set it when logging/queuing the event: \Zumba\Amplitude\Amplitude::getInstance() ->queueEvent('EVENT');
注意,在调用 queueEvent()
或 logEvent()
时设置它将覆盖事件对象中已设置的 eventType
,但事件上设置的任何其他属性将保持不变。
自定义事件工厂
比如说,你想要创建某种工厂,它可以生成要发送的事件,甚至可能每个事件都有自己的用户 ID 已设置... 你可以这样做
$amplitude = \Zumba\Amplitude\Amplitude::getInstance() ->init('APIKEY'); foreach ($eventFactory->getEvents() as $event) { $amplitude->event($event) ->queueEvent(); }
使用 event($array)
- 快速设置事件属性
在某些情况下,你可能只想快速设置下一个要队列或发送的事件的一些属性,但还不想真正发送或队列事件,你可以将属性数组传递给 $amplitude->event()
方法。
// Convenience way to quickly add properties to an event, just pass in array of properties to the event method: \Zumba\Zumba\Amplitude::getInstance()->event( [ 'eventProp' => 'Event Value', 'productId' => 'acme-widget-45', 'price' => 15.32, ] ); // The above is equivalent to: $event = \Zumba\Zumba\Amplitude::getInstance()->event(); $event->set( [ 'eventProp' => 'Event Value', 'productId' => 'acme-widget-45', 'price' => 15.32, ] );
queueEvent() 与 logEvent()
区别是什么?
- 两者都
- 需要设置非空的
eventType
。 logEvent()
:- 需要设置 API Key,如果没有设置,将抛出异常。
- 需要设置
userId
或deviceId
,如果没有在 amplitude 实例或事件本身上设置,将抛出异常。 - 始终在调用时发送事件,假设满足要求。
queueEvent()
:- 不 需要 首先设置 API Key。
- 不 需要 首先设置
userId
或deviceId
。 - 如果这些都没有设置,或者队列中还有未发送的事件,它将事件添加到内部队列中。这个队列不会跨页面加载持久化,如果队列中还有事件,如果在那个页面加载期间没有发送,它们将会丢失。
- 如果这些要求 已经 设置,并且队列中没有事件,它将立即发送。所以如果你已经初始化了 Amplitude,设置了 API key 和
userId
或deviceId
,当你调用queueEvent()
时,它的行为将完全与调用logEvent()
相同。 - 如果你使用这个功能,在初始化 Amplitude(设置 API key 和 amplitude 中的
userId
或deviceId
)之后,务必调用$amplitude->logQueuedEvents()
来发送队列中的任何事件。如果没有事件在队列中,不用担心,什么都不会发生。
为什么你会选择使用 logEvent()
而不是 queueEvent()
?这种情况适用于发送多个用户的事件,您会初始化数据然后立即发送。在这种情况下使用 logEvent()
,您可以立即捕获到如果没有正确初始化的情况(它将抛出一个逻辑异常),而不是“安静”地启动一个您可能永远不会处理的队列。
总结:如果您知道您将在调用事件之前始终初始化 Amplitude,则可以直接使用 logEvent()
。否则,请使用 queueEvent()
,并确保在初始化 Amplitude 并设置用户数据后,调用一次 $amplitude->logQueuedEvents()
。