Action Handlers
After a targeting rule matches, it runs one or more configured actions. Action handlers, services implementing
ActionHandlerInterface,
execute these actions.
Shipped Action Handlers
The bundle registers the following action handlers by default (config/pimcore/default.yaml); the action key is
what appears in rule configuration and in the pimcore_personalization.targeting.action_handlers map:
| Action key | Class |
|---|---|
assign_target_group | Pimcore\Bundle\PersonalizationBundle\Targeting\ActionHandler\AssignTargetGroup |
codesnippet | Pimcore\Bundle\PersonalizationBundle\Targeting\ActionHandler\CodeSnippet |
redirect | Pimcore\Bundle\PersonalizationBundle\Targeting\ActionHandler\Redirect |
As with conditions, a custom action handler has two parts:
- A PHP class implementing
ActionHandlerInterface. See the shipped implementations for reference. - A Pimcore Studio dynamic type so the action appears on the Actions tab of a targeting rule. See Registering in Pimcore Studio below.
Implementing an Action Handler
As an example, implement a simple Log action handler that logs each matched rule with a configured log level.
The action handler is a normal service that can depend on other services, as this one depends on the logger.
Don't rely on a visitor ID being set or a rule being passed. The visitor ID may not exist yet on a visitor's first request, and action handlers can run outside the matching engine without a rule. Always check these values before using them.
<?php
// src/Targeting/ActionHandler/Log.php
namespace App\Targeting\ActionHandler;
use Pimcore\Bundle\PersonalizationBundle\Model\Tool\Targeting\Rule;
use Pimcore\Bundle\PersonalizationBundle\Targeting\ActionHandler\ActionHandlerInterface;
use Pimcore\Bundle\PersonalizationBundle\Targeting\Model\VisitorInfo;
use Psr\Log\LoggerInterface;
class Log implements ActionHandlerInterface
{
private LoggerInterface $logger;
public function __construct(LoggerInterface $logger)
{
$this->logger = $logger;
}
public function apply(VisitorInfo $visitorInfo, array $action, ?Rule $rule = null): void
{
$level = $action['level'] ?? 'info';
$this->logger->log(
$level,
'Matched target rule {ruleName} for visitor ID {visitorID} with config {config}',
[
'visitorID' => $visitorInfo->hasVisitorId() ? $visitorInfo->getVisitorId() : '(no visitor ID)',
'ruleName' => $rule ? $rule->getName() : '(no rule)',
'config' => json_encode($action)
]
);
}
}
Next, register your action handler as a service. This example relies on autowiring to inject the logger automatically; if you don't use autowiring, wire the dependency in the service definition instead.
services:
_defaults:
autowire: true
autoconfigure: true
public: false
App\Targeting\ActionHandler\Log: ~
As a last step, register the action handler with the targeting engine. Keep the identifier unique, since you'll reuse it when registering the Studio dynamic type.
pimcore_personalization:
targeting:
action_handlers:
log: App\Targeting\ActionHandler\Log
Postponed Actions
If your action handler needs to apply data at a later stage of the request/response cycle, it can register an
action on the VisitorInfo for later consumption. Currently only the response action scope is defined, applied
during the onKernelResponse event, but more action scopes may be added in the future.
See the
CodeSnippet
action handler as an example. It registers an action via $visitorInfo->addAction() and implements
ResponseTransformingActionHandlerInterface::transformResponse(), which the targeting engine calls for every
action registered with the response scope.
Registering in Pimcore Studio
Registering the PHP action handler makes it usable in targeting rules, but it won't appear on the Actions tab of the Pimcore Studio rule editor until you also register a matching Studio dynamic type, the same way conditions do (see Conditions).
As with conditions, the rule builder has no global action registry. This bundle creates an instance of the SDK class
DynamicTypeRuleActionRegistry and binds it in the Studio DI container under the service ID
PersonalizationBundle/ActionRegistry. The Actions tab renders only the types held by that instance.
To add a Studio dynamic type for log, build a small Studio UI plugin bundle that:
- implements a dynamic type extending
DynamicTypeRuleActionAbstractfrom@pimcore/studio-ui-bundle/modules/rule-builder, decorated with@injectable(), usinglogas its type key so it matches the PHP registration, - binds that class in the container in the plugin's
onInit, - resolves
PersonalizationBundle/ActionRegistryand callsregisterDynamicType()on it in the plugin'sonStartup, for the same ordering reason described in the Conditions chapter.
See this bundle's own action dynamic types for concrete examples (for instance the Redirect action), and the Studio UI Bundle's Dynamic Types and Getting Started with Your First Plugin guides for the general plugin and dynamic type mechanism.