All docs / Developer Guide

Custom Conditions

Create custom conditions that filter when automation recipes execute.

Creating Custom Conditions

A condition filters whether a recipe’s actions should run. It evaluates to true (pass) or false (block).

Complete Example

This example creates a condition that checks if the user has a specific membership level:

<?php
// File: conditions/membership-level-condition.php

if ( ! defined( 'ABSPATH' ) ) exit;

class IW_MembershipLevel_Condition extends IW_Automation_Condition {

    /**
     * Allow users to add this condition multiple times
     * (e.g., to check for level Gold OR Platinum with separate entries).
     */
    public $allow_multiple = true;

    /**
     * Display name in the condition dropdown.
     */
    function get_title() {
        return 'If user membership level is ...';
    }

    /**
     * Restrict which triggers this condition works with.
     * Return an empty array or omit this method to allow all triggers.
     */
    function allowed_triggers() {
        return array(
            'IW_Purchase_Trigger',
            'IW_PageVisit_Trigger',
            'IW_Checkout_Trigger',
        );
    }

    /**
     * Define the admin form fields (new React admin).
     *
     * Field types: text, number, textarea, select, checkbox, dynasearch, html
     * See the Field Types section below for all options.
     */
    function get_field_schema() {
        $levels = my_plugin_get_membership_levels(); // your function
        $options = array();
        foreach ($levels as $level) {
            $options[] = array('value' => $level->id, 'label' => $level->name);
        }

        return array(
            array(
                'type'    => 'select',
                'name'    => 'level',
                'label'   => 'Membership Level',
                'options' => $options,
            ),
            array(
                'type'    => 'select',
                'name'    => 'comparison',
                'label'   => 'Comparison',
                'options' => array(
                    array('value' => 'is', 'label' => 'is'),
                    array('value' => 'is_not', 'label' => 'is not'),
                ),
            ),
        );
    }

    /**
     * Validate configuration. Return an error string if invalid.
     * Return nothing (or true/false/null) if valid.
     */
    function validate_entry($config) {
        if (empty($config['level'])) {
            return 'Please select a membership level.';
        }
    }

    /**
     * Evaluate the condition at runtime.
     *
     * @param array  $config  The saved configuration
     * @param object $trigger The trigger instance ($trigger->user_email, $trigger->pass_vars, etc.)
     * @return bool True = condition passes, false = condition fails (recipe stops)
     */
    function test($config, $trigger) {
        // Find the user
        $user = get_user_by('email', $trigger->user_email);
        if (!$user) return false;

        // Check membership (your plugin's function)
        $user_level = my_plugin_get_user_level($user->ID);

        if ($config['comparison'] === 'is') {
            return $user_level == $config['level'];
        } else {
            return $user_level != $config['level'];
        }
    }
}

// Register with InfusedWoo
iw_add_condition_class('IW_MembershipLevel_Condition');

Required Methods

MethodDescription
get_title()Name shown in the admin condition dropdown
test($config, $trigger)Evaluate the condition at runtime. Return true to pass, false to block.

Required for Admin Support

MethodDescription
get_field_schema()Define the form fields. Without this method, the condition shows as “legacy” (non-editable) in the new admin.
validate_entry($config)Validate the saved config. Return error string if invalid.

Optional Methods & Properties

Method/PropertyDescription
allowed_triggers()Array of trigger class names this condition works with. Omit for all.
$allow_multipleSet to true to let users add this condition multiple times

Field Types

Use these in your get_field_schema() return array:

Text Input

array('type' => 'text', 'name' => 'my_field', 'label' => 'My Field', 'placeholder' => 'Enter value...')

Text with Merge Field Picker

array('type' => 'text', 'name' => 'my_field', 'label' => 'My Field', 'merge_field' => true)

Number Input

array('type' => 'number', 'name' => 'amount', 'label' => 'Amount')
array('type' => 'select', 'name' => 'status', 'label' => 'Status', 'options' => array(
    array('value' => 'active', 'label' => 'Active'),
    array('value' => 'inactive', 'label' => 'Inactive'),
))

Multi-Select (searchable, with chips)

array('type' => 'select', 'name' => 'categories', 'label' => 'Categories', 'multiple' => true, 'options' => $options)

Checkbox

array('type' => 'checkbox', 'name' => 'strict', 'label' => 'Strict matching')

Check in PHP: $config['strict'] == 'on'

Conditional Visibility

Show a field only when another field has a specific value:

array('type' => 'text', 'name' => 'custom_id', 'label' => 'Custom ID', 'visible_when' => array('type' => 'custom'))

The Trigger Object

In test($config, $trigger), you can access:

PropertyDescription
$trigger->user_emailThe identified contact email
$trigger->pass_varsArray of event data from the trigger
$trigger->wp_user_idWordPress user ID (if available)

Tips

  • If your condition doesn’t need any configuration, still implement get_field_schema() returning an empty array — this prevents it from being marked as “legacy”
  • Use $allow_multiple = true for conditions that users might want to stack (e.g., checking different values of the same type)
  • The test() method should be fast — it runs on every trigger event for every recipe using this condition