Installation
composer require capitalise/intercom-bundle
Register the bundle in config/bundles.php:
return [
// ...
Capitalise\IntercomBundle\CapitaliseIntercomBundle::class => ['all' => true],
];
Configuration Publish the default config:
php bin/console capitalise:intercom:install
Update config/packages/capitalise_intercom.yaml with your Intercom API keys:
capitalise_intercom:
app_id: 'your_app_id'
api_key: 'your_api_key'
First Use Case Trigger a simple event in a controller:
use Capitalise\IntercomBundle\Service\IntercomService;
class UserController extends AbstractController
{
public function show(User $user, IntercomService $intercom)
{
$intercom->trackEvent($user->getEmail(), 'user_viewed_profile');
return $this->render('...');
}
}
User Tracking Attach Intercom to users on registration/login:
$intercom->createUser($user->getEmail(), [
'name' => $user->getFullName(),
'email' => $user->getEmail(),
'custom_attributes' => [
'account_type' => $user->getAccountType(),
],
]);
Event Tracking Log custom events with metadata:
$intercom->trackEvent($user->getEmail(), 'purchase_initiated', [
'amount' => $order->getTotal(),
'product_id' => $order->getProductId(),
]);
Conversations Trigger conversations programmatically:
$intercom->createConversation($user->getEmail(), [
'subject' => 'Order Confirmation',
'body' => 'Your order #'.$order->getId().' has been placed.',
]);
Symfony Events
Bind Intercom actions to Symfony events (e.g., kernel.request):
# config/services.yaml
services:
App\EventListener\IntercomListener:
tags:
- { name: kernel.event_listener, event: kernel.request, method: onKernelRequest }
public function onKernelRequest(GetResponseEvent $event)
{
$user = $this->getUser();
if ($user && $event->isMasterRequest()) {
$this->intercom->trackEvent($user->getEmail(), 'page_view', [
'url' => $event->getRequest()->getUri(),
]);
}
}
Twig Integration Pass Intercom data to templates:
{% if app.user %}
<script>
window.intercomSettings = {
app_id: "{{ app.parameters.capitalise_intercom.app_id }}"
};
</script>
<script src="https://widget.intercom.io/widget/{{ app.parameters.capitalise_intercom.app_id }}.js"></script>
{% endif %}
API Rate Limits
Intercom enforces rate limits.
Cache responses aggressively for getUser, getConversation, etc.:
$user = $intercom->getUser($email, ['cache' => true]);
User Identification
Ensure email or user_id is consistent across requests. Mixing identifiers (e.g., email vs. user_id) may create duplicate users.
Async Operations
Methods like createConversation are fire-and-forget. Handle failures gracefully:
try {
$intercom->createConversation($email, [...]);
} catch (\Exception $e) {
$this->logger->error('Intercom failure', ['error' => $e->getMessage()]);
}
Enable Debug Mode
Set debug: true in config to log API responses:
capitalise_intercom:
debug: true
Check var/log/dev.log for raw API calls/responses.
Mocking for Tests
Use the IntercomService interface to mock dependencies:
$mock = $this->createMock(IntercomService::class);
$mock->method('trackEvent')->willReturn(true);
Custom Attributes
Extend the bundle’s User DTO to add custom fields:
// src/Entity/IntercomUser.php
namespace App\Entity;
use Capitalise\IntercomBundle\Model\User as BaseUser;
class IntercomUser extends BaseUser
{
public function getCustomAttributes()
{
return array_merge(parent::getCustomAttributes(), [
'custom_field' => $this->getSomeProperty(),
]);
}
}
Update the service to use your class:
capitalise_intercom:
user_class: App\Entity\IntercomUser
Webhook Handling
The bundle lacks built-in webhook support. Use Symfony’s HttpClient to validate and process Intercom webhooks:
use Symfony\Contracts\HttpClient\HttpClientInterface;
public function handleWebhook(HttpClientInterface $client, Request $request)
{
$signature = $request->headers->get('X-Intercom-Signature');
$payload = $request->getContent();
$isValid = $client->request('GET', 'https://api.intercom.io/verify', [
'query' => [
'signature' => $signature,
'timestamp' => $request->headers->get('X-Intercom-Timestamp'),
],
'body' => $payload,
])->getStatusCode() === 200;
if ($isValid) {
// Process payload
}
}
How can I help you explore Laravel packages today?