Zum Inhalt springen

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.

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.

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.

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 resultIds in 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.

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');

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');

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.

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;
}
  1. Öffnen Sie die Zielgruppe und wählen Sie + an dem Knoten, dessen Datensätze Sie filtern möchten.
  2. Wählen Sie Benutzerdefinierter Filter.
  3. Wählen Sie Ihre Klasse unter Filter. Die Beschreibung erscheint unterhalb der Auswahl.
  4. Füllen Sie die Einstellungen aus, die der Filter deklariert.
  5. Wählen Sie Ohne, um die von Ihrem Filter zurückgegebenen Datensätze zu entfernen, statt sie zu behalten.
  6. 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.

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.

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.