fluentcrm-funnel-action
FluentCRM: register a custom funnel action
For developers building a companion plugin that needs to add a step inside FluentCRM's automation funnel — "Enroll user to LMS course", "Issue Woo coupon", "Send to webhook", "Update post status". Each action is a block the admin drags into the funnel sequence; when a contact reaches the block, the handler runs once per (contact, sequence) tuple. Extends FluentCrm\App\Services\Funnel\BaseAction. Verified end-to-end against FluentCRM 3.1.8 source.
API stability note
BaseAction, the fluentcrm_funnel_blocks / fluentcrm_funnel_block_fields filter pair, the per-action fluentcrm_funnel_sequence_handle_{name} action, and the (subscriber, sequence, funnelSubscriberId, funnelMetric) handler signature have been stable since 2.7. The implicit sequence-progress pattern (FunnelProcessor sets last_sequence_status = 'complete' before dispatching the handler) has been in place since 1.2 of the funnel processor.
Misconception this skill corrects
"I'll mark the sequence as
'completed'from my handler when the work succeeds."
Two bugs in one sentence.
Bug A: the canonical string depends on the column. FunnelProcessor::processSequence() writes FunnelSubscriber.last_sequence_status = 'complete' through FunnelHelper::changeFunnelSubSequenceStatus(). The full automation run status uses FunnelSubscriber.status = 'completed', and FunnelMetric.status defaults to 'completed' in the migration/model. Writing 'completed' to last_sequence_status is wrong; writing 'complete' to FunnelMetric.status is also wrong for the current reporting model.
Bug B: you don't need to mark anything as complete on success. FunnelProcessor::processSequence() calls FunnelHelper::changeFunnelSubSequenceStatus($funnelSubscriberId, $sequence->id, 'complete') before firing do_action('fluentcrm_funnel_sequence_handle_' . $sequence->action_name, ...). By the time your handler runs, the sequence is already marked 'complete'. Your job is to override only when you want a different outcome: