Benutzerdefinierte Filter
Ein benutzerdefinierter Filter führt Ihre eigene Apex-Logik auf den Datensätzen aus, die eine Zielgruppe bis dahin eingegrenzt hat, und behält die Datensätze, die Ihre Logik akzeptiert. Verwenden Sie ihn, wenn sich die Regel nicht über Felder und verknüpfte Objekte ausdrücken lässt – etwa ein Berechtigungsservice, ein Scoring-Modell, eine Prüfung gegen ein externes System oder jede Entscheidung, die bereits in Ihrem eigenen Code liegt.
Sobald eine Klasse bereitgestellt ist, erscheint sie im Zielgruppen-Builder als Benutzerdefinierter Filter, neben Übergeordnete Beziehung, Verwandte Datensätze und Aggregat. Die Option wird nur bei Objekten angeboten, die Ihre Klasse unterstützt. In einer Organisation ohne benutzerdefinierte Filter ändert sich also nichts.
Die Schnittstelle
Abschnitt betitelt „Die Schnittstelle“Ein benutzerdefinierter Filter ist eine Apex-Klasse, die lb.CustomFilter_Interface implementiert:
global interface CustomFilter_Interface { Set<Id> filter(Set<Id> resultIds, List<CustomFilterParameter> parameters, CustomFilterContext context); List<SObjectType> forObjects(); List<CustomFilterParameter> getParameters(); String getLabel(); String getDescription();}| Methode | Aufgabe | Wann CAB sie aufruft |
|---|---|---|
filter |
Entscheidet, welche Datensätze bestehen bleiben. Geben Sie die Teilmenge von resultIds zurück, die den Filter besteht; alles Weggelassene wird aus der Zielgruppe entfernt. |
Einmal pro Batch bei jedem Zielgruppenlauf und erneut für die Datensatzzahlen, die während der Bearbeitung angezeigt werden. |
forObjects |
Deklariert, an welchen Objekten der Filter verwendet werden darf. Geben Sie null oder eine leere Liste zurück, um alle Objekte zuzulassen. |
Wenn der Builder entscheidet, ob Benutzerdefinierter Filter an einem Knoten angeboten wird. |
getParameters |
Deklariert die benötigte Konfiguration. CAB rendert pro Parameter ein Eingabefeld und übergibt die Werte an filter. Geben Sie null zurück, wenn keine benötigt werden. |
Wenn der Builder die Einstellungen des Filters rendert, und erneut vor jedem Lauf, um gespeicherte Werte mit Ihren Deklarationen zusammenzuführen. |
getLabel |
Der Name, den Benutzer auswählen. Ohne ihn müssten sie den Namen Ihrer Apex-Klasse lesen. | Überall dort, wo der Filter aufgelistet oder angezeigt wird. |
getDescription |
Ein bis zwei Sätze, die erklären, was der Filter tut. Wird unter der Auswahl angezeigt und an Cabby übergeben, damit er den Filter einordnen kann. | Wie getLabel. |
In der Praxis erweitern Sie lb.CustomFilterBase, statt die Schnittstelle direkt zu implementieren. Sie liefert für jede Methode außer filter eine Vorgabe, sodass Sie nur schreiben, was Ihr Filter wirklich benötigt, und ergänzt Hilfsmethoden zum Lesen von Parameterwerten.
Ihre Klasse muss global sein und einen zugänglichen Konstruktor ohne Argumente besitzen.
Filter schreiben
Abschnitt betitelt „Filter schreiben“Dieser Filter fragt einen Berechtigungsservice, den die Organisation bereits besitzt, welche der aktuellen Datensätze für ein Angebot infrage kommen, und behält diese. Was dieser Service tut – ein Scoring-Modell, eine Regel-Engine, ein Aufruf in ein anderes System – ist für CAB unerheblich; die einzige Aufgabe des Filters besteht darin, dessen Antwort in eine Menge von IDs zu übersetzen.
global with sharing class OfferEligibility extends lb.CustomFilterBase {
global override String getLabel() { return 'Für Angebot berechtigt'; }
global override String getDescription() { return 'Behält Datensätze, die der Berechtigungsservice für das gewählte Angebot freigibt.'; }
global override List<SObjectType> forObjects() { return new List<SObjectType>{ Contact.SObjectType }; }
global override List<lb.CustomFilterParameter> getParameters() { lb.CustomFilterParameter offer = new lb.CustomFilterParameter( 'offerCode', 'Angebotscode', lb.CustomFilterParameter.DATA_TYPE_TEXT ); offer.description = 'Das Angebot, gegen das die Berechtigung geprüft wird.'; offer.isRequired = true;
return new List<lb.CustomFilterParameter>{ offer }; }
global override Set<Id> filter(Set<Id> resultIds, List<lb.CustomFilterParameter> parameters, lb.CustomFilterContext context) {
String offerCode = lb.CustomFilterBase.stringValue(parameters, 'offerCode');
// Ihre eigene Logik. CAB weiß nicht, was hier geschieht, und muss es auch nicht wissen. Map<Id, Boolean> approved = OfferEligibilityService.evaluate(resultIds, offerCode);
Set<Id> passing = new Set<Id>(); for (Id recordId : resultIds) { if (approved.get(recordId) == true) { passing.add(recordId); } } return passing; }}Der Benutzer fügt diesen Filter einer Kontakt-Zielgruppe hinzu, gibt einen Angebotscode ein, und jeder vom Service abgelehnte Kontakt fällt aus der Zielgruppe heraus.
Wie filter aufgerufen wird
Abschnitt betitelt „Wie filter aufgerufen wird“filter ist ein Prädikat über die übergebenen Datensätze, nicht über die gesamte Zielgruppe. CAB verarbeitet große Zielgruppen in Batches und ruft Ihre Methode daher einmal pro Batch auf, jedes Mal mit einer anderen Teilmenge der IDs. Für jeden Aufruf wird eine neue Instanz erzeugt; Instanzzustand bleibt zwischen den Aufrufen also nicht erhalten.
Zwei Konsequenzen sollten Sie einplanen:
- Logik, die alle Datensätze gleichzeitig sehen muss – etwa „die 100 Kontakte mit dem höchsten Score“ – lässt sich in einem benutzerdefinierten Filter nicht abbilden, weil kein einzelner Aufruf die gesamte Zielgruppe sieht. Bewerten Sie stattdessen innerhalb Ihrer eigenen Logik gegen einen festen Schwellenwert.
- Die Arbeit wiederholt sich pro Batch. Übergeben Sie die gesamte Menge
resultIdsin einem Aufruf an Ihren Service, wie im Beispiel, statt pro Datensatz aufzurufen.
Zurückgegebene IDs, die nicht zum Objekt der Zielgruppe gehören oder nicht in resultIds enthalten waren, werden abgelehnt oder ignoriert. Ein benutzerdefinierter Filter kann eine Zielgruppe immer nur eingrenzen, niemals erweitern.
Konfiguration deklarieren
Abschnitt betitelt „Konfiguration deklarieren“Jeder lb.CustomFilterParameter, den Sie aus getParameters zurückgeben, wird zu einem Eingabefeld in den Einstellungen des Filters.
| Eigenschaft | Zweck |
|---|---|
name |
Der Schlüssel, über den Sie den Wert wieder auslesen. Muss innerhalb des Filters eindeutig sein. |
label |
Wird über dem Eingabefeld angezeigt. |
description |
Optionaler Hilfetext zum Eingabefeld. |
dataType |
Welches Eingabefeld gerendert wird. Siehe Tabelle unten. |
isRequired |
Bei true kann die Zielgruppe ohne Wert weder gespeichert noch ausgeführt werden. |
referenceSettings |
Bei einem Datensatz-Parameter, aus welchem Objekt ausgewählt wird und ob mehrere Datensätze zulässig sind. |
picklistSettings |
Bei einem Auswahllisten-Parameter, woher die Auswahlwerte stammen und ob mehrere zulässig sind. |
value |
Bei der Deklaration die Vorgabe; beim Rückweg an filter der konfigurierte Wert. |
| Datentyp | Konstante | Darstellung |
|---|---|---|
| Text | DATA_TYPE_TEXT |
Textfeld |
| Zahl | DATA_TYPE_NUMBER |
Zahlenfeld |
| Kontrollkästchen | DATA_TYPE_BOOLEAN |
Kontrollkästchen |
| Datum | DATA_TYPE_DATE |
Datumsfeld |
| Datum und Uhrzeit | DATA_TYPE_DATETIME |
Datums- und Uhrzeitfeld |
| Auswahlliste | DATA_TYPE_PICKLIST |
Auswahlliste, einfach oder mehrfach |
| Datensatz | DATA_TYPE_ID |
Datensatzauswahl, einfach oder mehrfach |
Werte erreichen Ihre Klasse immer als Text. Lesen Sie sie mit den Hilfsmethoden auf lb.CustomFilterBase, statt sie selbst zu parsen:
String offerCode = lb.CustomFilterBase.stringValue(parameters, 'offerCode');Decimal threshold = lb.CustomFilterBase.decimalValue(parameters, 'threshold');Boolean active = lb.CustomFilterBase.booleanValue(parameters, 'activeOnly');Date since = lb.CustomFilterBase.dateValue(parameters, 'since');Datetime cutoff = lb.CustomFilterBase.datetimeValue(parameters, 'cutoff');Id campaignId = lb.CustomFilterBase.idValue(parameters, 'campaignId');Datensatz-Parameter
Abschnitt betitelt „Datensatz-Parameter“Verwenden Sie den Konstruktor mit einem SObjectType. Ihre Klasse erhält die ID des ausgewählten Datensatzes.
lb.CustomFilterParameter campaign = new lb.CustomFilterParameter( 'campaignId', 'Mitglied der Kampagne', Campaign.SObjectType);Mit true als viertem Argument können mehrere Datensätze statt nur einem ausgewählt werden. Lesen Sie die Auswahl mit idValues — die Methode liefert bei beiden Varianten eine Liste, sodass Sie einen Parameter später auf Mehrfachauswahl umstellen können, ohne das Auslesen zu ändern.
lb.CustomFilterParameter campaigns = new lb.CustomFilterParameter( 'campaignIds', 'Mitglied einer dieser Kampagnen', Campaign.SObjectType, true);
List<Id> campaignIds = lb.CustomFilterBase.idValues(parameters, 'campaignIds');Auswahllisten-Parameter
Abschnitt betitelt „Auswahllisten-Parameter“Die Auswahlwerte stammen aus einer von zwei Quellen; welche es ist, bestimmen Sie über den aufgerufenen Konstruktor.
Aus einem Salesforce-Auswahllistenfeld: dessen aktive Werte und die übersetzten Bezeichnungen des Benutzers werden bei jedem Öffnen des Filters neu gelesen und bleiben so aktuell, wenn sich das Feld ändert.
lb.CustomFilterParameter sources = new lb.CustomFilterParameter( 'leadSources', 'Lead-Quellen', new lb.CustomFilterParameter.PicklistSettings(Contact.LeadSource, true));Oder aus einer festen Liste, die Sie selbst deklarieren — für Auswahlwerte, die zu Ihrem Filter gehören und nicht zu einem Feld:
lb.CustomFilterParameter mode = new lb.CustomFilterParameter( 'mode', 'Abgleichmodus', new lb.CustomFilterParameter.PicklistSettings(new List<String>{ 'Strikt', 'Locker' }));In beiden Fällen macht das zweite Argument den Parameter zur Mehrfachauswahl. Eine einzelne Auswahl lesen Sie mit stringValue, eine Mehrfachauswahl mit stringValues:
String mode = lb.CustomFilterBase.stringValue(parameters, 'mode');List<String> leadSources = lb.CustomFilterBase.stringValues(parameters, 'leadSources');Ein Filter, der weder ein Feld noch eine Werteliste deklariert, gilt als fehlerhaft und erscheint nicht im Builder.
Wenn ein Auswahlwert wegfällt — ein Auswahllistenwert wird deaktiviert oder Sie kürzen Ihre eigene Liste —, schlägt eine Zielgruppe, die noch damit konfiguriert ist, zu Beginn ihrer Ausführung fehl und nennt dabei Wert und Einstellung. Sie wird nicht stillschweigend ignoriert, denn ein Filter, der nichts trifft, sieht aus wie einer, der funktioniert.
Parameter werden über name zugeordnet. Sie können sie also später ergänzen, entfernen oder umsortieren. Werte zu einem entfernten Parameter werden verworfen, und ein neu hinzugefügter Parameter verwendet seine deklarierte Vorgabe, bis jemand den Filter bearbeitet.
Ausführungskontext lesen
Abschnitt betitelt „Ausführungskontext lesen“lb.CustomFilterContext beschreibt den Aufruf:
| Eigenschaft | Verwendung |
|---|---|
objectName |
Das gefilterte Objekt. Jede ID in resultIds gehört zu diesem Typ. |
audienceVersionId |
Die Zielgruppenversion, zu der dieser Lauf gehört. |
nodeId |
Die Datensatz-ID des Filterknotens, nützlich für Protokollierung. |
nodeLabel |
Der Name des Knotens auf dem Canvas — das, was getLabel zurückgegeben hat, oder der Name, den der Benutzer stattdessen vergeben hat. |
isExclusion |
true, wenn der Knoten auf Ohne gesetzt ist. CAB kehrt das Ergebnis für Sie um – kehren Sie es nicht selbst um. |
isPreview |
true, wenn eine Datensatzzahl für den Builder erzeugt wird, statt die Zielgruppe auszuführen. |
Am wichtigsten ist isPreview. Die Zahlen, die während der Bearbeitung einer Zielgruppe angezeigt werden, rufen ebenfalls Ihren Filter auf. Ein Filter, der ein externes System anspricht, sollte den Aufruf während einer Vorschau daher überspringen oder eine günstigere Näherung zurückgeben.
if (context.isPreview) { return resultIds;}Filter zu einer Zielgruppe hinzufügen
Abschnitt betitelt „Filter zu einer Zielgruppe hinzufügen“- Öffnen Sie die Zielgruppe und wählen Sie + an dem Knoten, dessen Datensätze Sie filtern möchten.
- Wählen Sie Benutzerdefinierter Filter.
- Wählen Sie Ihre Klasse unter Filter. Die Beschreibung erscheint unterhalb der Auswahl.
- Füllen Sie die Einstellungen aus, die der Filter deklariert.
- Wählen Sie Ohne, um die von Ihrem Filter zurückgegebenen Datensätze zu entfernen, statt sie zu behalten.
- Wählen Sie Speichern.
Der Filter erscheint als Knoten auf dem Canvas unter dem Namen, den Ihre Klasse aus getLabel zurückgibt. Wählen Sie den Namen des Knotens, um ihn umzubenennen — eine spätere Neukonfiguration des Filters lässt Ihren Namen unangetastet. Mit einem Doppelklick auf den Knoten ändern Sie Klasse oder Einstellungen.
Ein benutzerdefinierter Filter wird mit seinen Geschwisterfiltern genauso kombiniert wie jeder andere Filter über verwandte Datensätze, einschließlich benutzerdefinierter Filterlogik. Da die Apex-Logik eigenständig entscheidet, können unterhalb des Filters keine weiteren Filter hinzugefügt werden.
Benutzerdefinierte Filter lassen sich auch als Teil eines Eintrags der Filterbibliothek verwenden, sodass eine Regel einmal gepflegt und in mehreren Zielgruppen wiederverwendet werden kann.
Limits und Fehlerbehandlung
Abschnitt betitelt „Limits und Fehlerbehandlung“Ihre Klasse läuft in der Transaktion des Zielgruppenlaufs und teilt sich deren Governor Limits. Fragen Sie gegen die übergebene ID-Menge ab, statt in Schleifen abzufragen, und halten Sie den Aufwand proportional zu einem einzelnen Batch.
Callouts sind erlaubt, zählen aber auf die Limits der Transaktion und unterliegen der Salesforce-Regel, dass nach nicht festgeschriebenem DML kein Callout erfolgen darf.
Löst Ihre Klasse eine Ausnahme aus, schlägt der Zielgruppenlauf mit einer Fehlermeldung fehl, die die Klasse benennt. Wurde die Klasse seit dem Speichern der Zielgruppe umbenannt oder gelöscht, schlägt der Lauf sofort mit einer erklärenden Meldung fehl statt mittendrin.
Für Administratoren
Abschnitt betitelt „Für Administratoren“CAB-Einstellungen › Benutzerdefinierte Filter erklärt die Funktion, verweist auf diese Seite, listet alle in Ihrer Organisation gefundenen benutzerdefinierten Filter auf und stellt eine Beispielimplementierung zum Kopieren bereit.
Benutzer benötigen zusätzlich zu ihren Campaign-Audience-Builder-Berechtigungen Zugriff auf Ihre Apex-Klasse. Da die Klasse in Ihrer Organisation und nicht im Paket liegt, wird ihr Zugriff nicht durch die mitgelieferten Berechtigungssätze erteilt. Nehmen Sie die Klasse selbst in einen Berechtigungssatz auf, sonst erhalten Benutzer beim Ausführen der Zielgruppe einen Fehler wegen fehlenden Klassenzugriffs.

