# Benchmark

Benchmark is a goal or target that you want to reach. For example, when a user clicks on a link in your email then it can be a benchmark. When one or more tags are applied based on a trigger and a set of actions, then it can be a benchmark. A benchmark is the last step of an automation.

# Creating a Benchmark

Creating a benchmark is very much similar to creating a trigger or action with slight difference. You just need to extend the FluentCrm\App\Services\Funnel\BaseBenchmark class and implement the required methods. Let's assume some tags are applied for particular users when a course is enrolled. For those users, you want to end the automation. That means, they have reached the benchmark. Please, note that FluentCRM already has a tag benchmark. But, we are creating a custom benchmark for the sake of example.

Create a new class and extend the FluentCrm\App\Services\Funnel\BaseBenchmark class. Constructor of the class has the following body:

<?php
namespace Your\Plugin\Name\Automation;

use FluentCrm\App\Services\Funnel\BaseBenchmark;

class CourseEnrolledBenchmark extends BaseBenchmark {
        
    public function __construct()
    {
        $this->triggerName = 'course_enrolled_benchmark';
        $this->actionArgNum = 2;
        $this->priority = 20;
        parent::__construct();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Define the getBlock method. This method actually returns the block of the benchmark. The block is the UI of the benchmark.

    public function getBlock()
    {
        return [
            'category'    => __('MyTag Applied', 'your-plugin'),
            'title'       => __('Course Enrolled', 'your-plugin'),
            'description' => __('This will run when selected tags have been applied to a contact', 'your-plugin'),
            'icon'        => 'fc-icon-apply_list', // use any icon you like
            'settings'    => [
                'tags'        => [],
                'select_type' => 'any',
                'type'        => 'optional',
                'can_enter'   => 'yes'
            ]
        ];
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

define getDefaultSettings method. This method returns the default settings of the benchmark.

    public function getDefaultSettings()
    {
        return [
            'tags'        => [],
            'select_type' => 'any',
            'type'        => 'optional',
            'can_enter'   => 'yes'
        ];
    }
1
2
3
4
5
6
7
8
9

Now, you need to define getBlockFields method which returns the settings of the benchmark.

    public function getBlockFields()
    {
        $yourCustomTags = [
            [
                'id'    => 'your-tag-id',
                'title' => 'Your Tag Title',
            ],
            [
                'id'    => 'your-other-tag-id',
                'title' => 'Your Other Tag Title',
            ]
        ];
        return [
            'title'     => __('My Plugin Tag Applied', 'your-plugin'),
            'sub_title' => __('This will run when selected Tags have been applied to a contact', 'your-plugin'),
            'fields'    => [
                'tags'        => [
                    'type'        => 'multi-select',
                    'options'  => $yourCustomTags,
                    'is_multiple' => true,
                    'label'       => __('Select Tags', 'your-plugin'),
                    'placeholder' => __('Select Tags', 'your-plugin')
                ],
                'select_type' => [
                    'label'      => __('Run When', 'your-plugin'),
                    'type'       => 'radio',
                    'inline'     => true,
                    'options'    => [
                        [
                            'id'    => 'any',
                            'title' => __('contact added in any of the selected Tags', 'fluent-crm')
                        ],
                        [
                            'id'    => 'all',
                            'title' => __('contact added in all of the selected Tags', 'fluent-crm')
                        ]
                    ],
                    'dependency' => [
                        'depends_on' => 'tags',
                        'operator'   => '!=',
                        'value'      => ''
                    ]
                ]
            ]
        ];
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

Finally, you need to define handle method. This method is called when the benchmark is reached. You can do anything you want in this method.

    public function handle($benchMark, $originalArgs)
    {
        $tagIds = $originalArgs[0];
        $subscriber = $originalArgs[1];
        $settings = $benchMark->settings;

        $isMatched = array_intersect($settings['tags'], $tagIds);
        if (!$isMatched) {
            return false; // not in our scope
        }

        $marchType = Arr::get($settings, 'select_type');

        $subscriberTags = $subscriber->tags->pluck('id')->toArray();
        $intersection = array_intersect($tagIds, $subscriberTags);

        if ($marchType === 'any') {
            // At least one funnel list id is available.
            $isMatched = !empty($intersection);
        } else {
            // All the funnel list ids are present.
            $isMatched = count($intersection) === count($settings['tags']);
        }

        if (!$isMatched) {
            return false; // not in our scope
        }

        $funnelProcessor = new FunnelProcessor();
        $funnelProcessor->startFunnelFromSequencePoint($benchMark, $subscriber);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

Let's see what we have done in the handle method. First, we have checked if the tags applied to the subscriber are in our scope or not. If not, then we have returned false. Then, we have checked if the tags applied to the subscriber are matching with the tags of the benchmark or not. If not, then we have returned false. Finally, we have started the automation from the benchmark.

The full code of the benchmark should look follows:

<?php
namespace Your\Plugin\Name\Automation;

use FluentCrm\App\Services\Funnel\BaseBenchmark;
use FluentCrm\App\Services\Funnel\FunnelProcessor;
use FluentCrm\Includes\Helpers\Arr;

class CourseEnrolledBenchmark extends BaseBenchmark {
        
    public function __construct()
    {
        $this->triggerName = 'course_enrolled_benchmark';
        $this->actionArgNum = 2;
        $this->priority = 20;
        parent::__construct();
    }
    
    public function getBlock()
    {
        return [
            'category'    => __('MyTag Applied', 'your-plugin'),
            'title'       => __('Course Enrolled', 'your-plugin'),
            'description' => __('This will run when selected tags have been applied to a contact', 'your-plugin'),
            'icon'        => 'fc-icon-apply_list', // use any icon you like
            'settings'    => [
                'tags'        => [],
                'select_type' => 'any',
                'type'        => 'optional',
                'can_enter'   => 'yes'
            ]
        ];
    }
    public function getDefaultSettings()
    {
        return [
            'tags'        => [],
            'select_type' => 'any',
            'type'        => 'optional',
            'can_enter'   => 'yes'
        ];
    }
    
    public function getBlockFields()
    {
        $yourCustomTags = [
            [
                'id'    => 'your-tag-id',
                'title' => 'Your Tag Title',
            ],
            [
                'id'    => 'your-other-tag-id',
                'title' => 'Your Other Tag Title',
            ]
        ];
        return [
            'title'     => __('My Plugin Tag Applied', 'your-plugin'),
            'sub_title' => __('This will run when selected Tags have been applied to a contact', 'your-plugin'),
            'fields'    => [
                'tags'        => [
                    'type'        => 'multi-select',
                    'options'  => $yourCustomTags,
                    'is_multiple' => true,
                    'label'       => __('Select Tags', 'your-plugin'),
                    'placeholder' => __('Select Tags', 'your-plugin')
                ],
                'select_type' => [
                    'label'      => __('Run When', 'your-plugin'),
                    'type'       => 'radio',
                    'inline'     => true,
                    'options'    => [
                        [
                            'id'    => 'any',
                            'title' => __('contact added in any of the selected Tags', 'fluent-crm')
                        ],
                        [
                            'id'    => 'all',
                            'title' => __('contact added in all of the selected Tags', 'fluent-crm')
                        ]
                    ],
                    'dependency' => [
                        'depends_on' => 'tags',
                        'operator'   => '!=',
                        'value'      => ''
                    ]
                ]
            ]
        ];
    }
    
    public function handle($benchMark, $originalArgs)
    {
        $tagIds = $originalArgs[0];
        $subscriber = $originalArgs[1];
        $settings = $benchMark->settings;

        $isMatched = array_intersect($settings['tags'], $tagIds);
        if (!$isMatched) {
            return false; // not in our scope
        }

        $marchType = Arr::get($settings, 'select_type');

        $subscriberTags = $subscriber->tags->pluck('id')->toArray();
        $intersection = array_intersect($tagIds, $subscriberTags);

        if ($marchType === 'any') {
            // At least one funnel list id is available.
            $isMatched = !empty($intersection);
        } else {
            // All the funnel list ids are present.
            $isMatched = count($intersection) === count($settings['tags']);
        }

        if (!$isMatched) {
            return false; // not in our scope
        }

        $funnelProcessor = new FunnelProcessor();
        $funnelProcessor->startFunnelFromSequencePoint($benchMark, $subscriber);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121

# Registering the Benchmark

Your benchmark is ready to use. Now, you need to register it with FluentCRM.

add_action('fluent_crm/after_init', function () {
    new Your\Plugin\Name\Automation\CourseEnrolledBenchmark();
});
1
2
3