- Creating and Publishing a Form
- Instant Forms
- Conversational Form
- Create Multi Step Forms In WordPress
- Using Calculations in SureForms: A Step-by-Step Guide
- Calculation Formula Guide
- SureForms Login Block – Step-by-Step Guide
- SureForms Registration Block – Step-by-Step Guide
- SureForms – PDF Generation Feature
- GDPR Compliant Forms
- SureForms Integration with ActiveCampaign
- SureForms Integration with AgileCRM
- SureForms Integration with Airtable
- SureForms Integration with LatePoint
- SureForms Integration with FluentCRM
- Connect SureForms To Zapier
- Automate WordPress Forms with the Custom App Builder
- SureForms Integration with Telegram
- SureForms Integration with Breeze
- SureForms Integration with Brevo
- Unable to Upload SureForms ZIP: File Unzipped On Download
- Browser Support for SureForms
- Not Getting Update Notifications
- How To Rollback to Previous SureForms Versions
- Publishing Failed: Invalid JSON Response
- Troubleshooting Email Sending In SureForms
- SureForm Submissions Marked as Spam – How to Fix
- API Request Failed – Nonce Verification Error
- Fixing the “Destination folder already exists” Error When Installing SureForms
- How to Set Up SureForms with Caching Plugins
- srfm_enable_redirect_activation
- sureforms_plugin_action_links
- srfm_quick_sidebar_allowed_blocks
- srfm_integrated_plugins
- srfm_suretriggers_integration_data_filter
- srfm_form_submit_response
- srfm_enable_gutenberg_post_types
- srfm_languages_directory
- srfm_form_template
- srfm_disable_nps_survey
SureForms Pro WordPress Plugin Integrations – Developer Guide (WordPress-Based)
Overview
SureForms Pro WordPress Plugin Integrations system allows you to create integrations with WordPress plugins using a hybrid approach: JSON configuration for metadata and PHP classes for action execution.
Key Features
Plugin Detection – Automatic detection of active WordPress plugins
JSON Configuration – Metadata and fields defined in JSON
PHP Action Classes – Business logic handled in PHP classes
Test Workflows – Real execution testing with cleanup capabilities
Dynamic Fields – WordPress filter-based field discovery
Action Hooks – WordPress hook system integration
Quick Start Tutorial
Unlike generic API integrations that use only JSON, WordPress plugin integrations require:
- JSON Configuration – Basic metadata and field definitions
- PHP Action Classes – Business logic and plugin interaction
- WordPress Hooks – Integration with plugin’s action system
Step-by-Step Integration Creation
Step 1: Create the Integration Metadata (JSON)
Create a config.json file in your integration directory:
{
"id": "your-plugin",
"integration": {
"name": "Your Plugin",
"icon": "your-plugin.svg",
"website_url": "https://yourplugin.com",
"docs_url": "https://docs.yourplugin.com",
"category": "Your Category",
"description": "Integration with Your Plugin"
},
"provider": "wordpress",
"plugin_detection": {
"class": "YourPluginMainClass"
},
"auth": {
"type": "plugin_detection",
"test_endpoint": {
"method": "plugin_check",
"success_criteria": {
"plugin_active": true
}
}
},
"actions": [
{
"name": "Create Record",
"description": "Create a new record in Your Plugin",
"provider": "wordpress",
"handler": {
"type": "action",
"action": "your_plugin_create_record"
},
"fields": [
{
"key": "name",
"label": "Name",
"type": "text",
"required": true,
"placeholder": "Enter name",
"description": "Record name"
},
{
"key": "email",
"label": "Email",
"type": "email",
"required": true,
"placeholder": "[email protected]",
"description": "Email address"
}
],
"apis": {
"custom_fields": {
"filter": "your_plugin_get_custom_fields",
"response_type": "dynamic_fields",
"dependencies": []
}
}
}
]
}Key Configuration Elements:
- provider: “wordpress” – Identifies this as a WordPress plugin integration
- plugin_detection.class – WordPress class to check for plugin activation
- handler.type: “action” – Use WordPress action hooks for execution
- handler.action – WordPress action name (prefixed with srfm_ during execution)
- apis.filter – WordPress filter for dynamic field discovery
**Important Note: All action names and filter names defined in your config.json will be automatically prefixed with “srfm_” when used in the WordPress hook system. For example:
- Action “your_plugin_create_record” becomes WordPress action srfm_your_plugin_create_record
Filter “your_plugin_get_custom_fields” becomes WordPress filter srfm_your_plugin_get_custom_fields
You must use these prefixed names when registering your callbacks in PHP code.
Step 2: Create the PHP Action Class
Create your action class extending WordPress_Action:
<?php
namespace SRFM_Pro\Inc\Pro\Native_Integrations\Integrations\YourPlugin\Actions;
use SRFM_Pro\Inc\Pro\Native_Integrations\WordPress_Action;
use SRFM_Pro\Inc\Traits\Get_Instance;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class Create_Record extends WordPress_Action {
use Get_Instance;
/**
* Integration name
*/
protected $integration = 'YourPlugin';
/**
* Action name
*/
protected $action = 'create_record';
/**
* Check if plugin is active
*/
protected function is_plugin_active() {
return class_exists( 'YourPluginMainClass' );
}
/**
* Execute the action
*
* @param array $data Form submission data.
* @return array|WP_Error Result of the action execution.
*/
protected function execute( $data ) {
// Check if this is test mode execution
is_test_mode = isset( $data['_test_mode'] ) && true === data['_test_mode'];
// Remove test mode flags from data for processing
if ( $is_test_mode ) {
unset( $data['_test_mode'] );
// Add test identifier if needed
data['notes'] = ( data['notes'] ?? '' ) . "\n\n[TEST RECORD - Created by SureForms workflow test]";
}
// Validate required data
$required_fields = [ 'name', 'email' ];
validation = $this->validate_required_fields( $data, required_fields );
if ( is_wp_error( $validation ) ) {
return $validation;
}
try {
// Your plugin's business logic here
$record = new \YourPluginRecordModel();
$record->set_data([
'name' => $data['name'],
'email' => $data['email'],
'notes' => $data['notes'] ?? '',
]);
if ( ! $record->save() ) {
throw new \Exception( 'Failed to save record.' );
}
// Fire plugin's native hooks if available
do_action( 'your_plugin_record_created', $record );
return [
'success' => true,
'message' => __( 'Record created successfully!', 'sureforms-pro' ),
'record_id' => $record->id,
];
} catch ( \Exception $e ) {
return new \WP_Error(
'record_creation_failed',
sprintf(
__( 'Record creation failed: %s', 'sureforms-pro' ),
$e->getMessage()
)
);
}
}
}
// Initialize the action when this file is loaded
Create_Record::get_instance();Step 3: Create the Integration Handler
Create an integration handler to manage filters and load action files:
<?php
namespace SRFM_Pro\Inc\Pro\Native_Integrations\Integrations\YourPlugin;
use SRFM_Pro\Inc\Traits\Get_Instance;
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly.
}
class YourPlugin_Integration {
use Get_Instance;
public function __construct() {
$this->register_filters();
}
/**
* Get custom fields from your plugin
*/
public function get_custom_fields( $fields = [] ) {
if ( ! $this->is_plugin_active() ) {
return $fields;
}
try {
// Your plugin's custom field discovery logic
$custom_fields = \YourPluginCustomFields::get_all_fields();
$formatted_fields = [];
foreach ( custom_fields as field ) {
$formatted_fields[] = [
'key' => $field['id'],
'label' => $field['label'],
'type' => $field['type'],
'required' => $field['required'] ?? false,
'description' => $field['description'] ?? '',
];
}
return $formatted_fields;
} catch ( \Exception $e ) {
return $fields;
}
}
/**
* Check if plugin is active
*/
private function is_plugin_active() {
return class_exists( 'YourPluginMainClass' );
}
/**
* Register WordPress filters
*/
private function register_filters() {
if ( ! $this->is_plugin_active() ) {
return;
}
// Register filter for dynamic fields
add_filter( 'srfm_your_plugin_get_custom_fields', [ $this, 'get_custom_fields' ] );
// Load action files
$this->load_action_files();
}
/**
* Load action files
*/
private function load_action_files() {
$action_files = [
__DIR__ . '/actions/create-record.php',
];
foreach ( action_files as file ) {
if ( file_exists( $file ) ) {
require_once $file;
}
}
}
}
// Initialize the integration
YourPlugin_Integration::get_instance();Step 4: Register Your Integration
WordPress plugin integrations require two separate filter registrations. Add both to your plugin’s initialization file:
4.1: Register JSON Configuration
// Register the JSON configuration
add_filter( 'srfm_pro_native_integrations_json_configs', 'add_your_plugin_integration_config' );
function add_your_plugin_integration_config( $json_configs ) {
// Your JSON configuration from Step 1
$your_plugin_config = [
'integrations' => [
[
'id' => 'your-plugin',
'integration' => [
'name' => 'Your Plugin',
'icon' => 'your-plugin.svg',
'website_url' => 'https://yourplugin.com',
'docs_url' => 'https://docs.yourplugin.com',
'category' => 'Your Category',
'description' => 'Integration with Your Plugin'
],
'provider' => 'wordpress',
'plugin_detection' => [
'class' => 'YourPluginMainClass'
],
'auth' => [
'type' => 'plugin_detection',
'test_endpoint' => [
'method' => 'plugin_check',
'success_criteria' => [
'plugin_active' => true
]
]
],
'actions' => [
// Your actions from JSON config
]
]
]
];
json_configs[] = wp_json_encode( your_plugin_config );
return $json_configs;
}4.2: Register PHP Handler Files
// Register the PHP integration handler
add_filter( 'srfm_pro_wordpress_plugin_integrations', 'register_your_plugin_integration_handler' );
function register_your_plugin_integration_handler( $plugin_integrations ) {
$plugin_integrations['yourplugin'] = [
'file' => plugin_dir_path( __FILE__ ) . 'integrations/sureforms/actions.php',
'detection' => 'YourPluginMainClass', // Your plugin's main class
];
return $plugin_integrations;
}
Registration Details:
JSON Configuration Filter (srfm_pro_native_integrations_json_configs):
- Provides the integration metadata, fields, and action definitions
- Must be JSON-encoded string added to the configs array
- Contains the complete JSON structure from Step 1
PHP Handler Filter (srfm_pro_wordpress_plugin_integrations):
- Registers the PHP files that contain action classes
- file: Path to your integration handler file (actions.php)
- detection: Main class name used to detect if your plugin is active
This dual-filter approach allows your plugin to register its SureForms integration without requiring modifications to the SureForms Pro codebase.
WordPress Action Classes
Base Class: WordPress_Action
All WordPress plugin actions must extend the WordPress_Action base class:
abstract class WordPress_Action {
/**
* Integration name - must be set in child class
*/
protected $integration = '';
/**
* Action name - must be set in child class
*/
protected $action = '';
/**
* Check if target plugin is active - must be implemented
*/
abstract protected function is_plugin_active();
/**
* Execute the action - must be implemented
*/
abstract protected function execute( $data );
/**
* Validate required fields - utility method
*/
protected function validate_required_fields( data, required_fields ) {
// Built-in validation logic
}
/**
* Store result for retrieval by provider - utility method
*/
protected function store_result( $result ) {
// Built-in result storage
}
}Action Registration
Actions are automatically registered when their files are loaded. The base class handles:
- WordPress Hook Registration – Registers action hook using srfm_{integration}_{action} pattern
- Error Handling – Catches exceptions and converts to WP_Error
- Result Storage – Stores results for provider retrieval
- Plugin Detection – Validates the plugin is active before execution
Test Mode Handling
WordPress actions support test mode execution:
protected function execute( $data ) {
// Check if this is test mode execution
is_test_mode = isset( $data['_test_mode'] ) && true === data['_test_mode'];
// Remove test mode flags from data
if ( $is_test_mode ) {
unset( $data['_test_mode'] );
// Add test identifiers if needed
data['notes'] = ( data['notes'] ?? '' ) . "\n\n[TEST RECORD]";
}
// Same execution logic for both test and real mode
// Test mode executes real operations - no simulation
}Field Types Reference
Static Fields (JSON Configuration)
{
"key": "field_name",
"label": "Field Label",
"type": "text|email|password|number|textarea|dropdown",
"required": true|false,
"placeholder": "Placeholder text",
"description": "Field description",
"options": [
{"label": "Option 1", "value": "value1"},
{"label": "Option 2", "value": "value2"}
]
}Dynamic Fields (WordPress Filters)
Dynamic fields are discovered through WordPress filters:
{
"apis": {
"custom_fields": {
"filter": "your_plugin_get_custom_fields",
"response_type": "dynamic_fields",
"dependencies": []
}
}
}The corresponding PHP filter:
add_filter( 'srfm_your_plugin_get_custom_fields', function( $fields ) {
return [
[
'key' => 'custom_field_1',
'label' => 'Custom Field 1',
'type' => 'text',
'required' => false,
'description' => 'A custom field',
]
];
});
Advanced Features
Field Dependencies
Create dependent dropdowns using WordPress filters:
{
"fields": [
{
"key": "category_id",
"label": "Select Category",
"type": "select-async",
"exclude_from_payload": true
},
{
"key": "item_id",
"label": "Select Item",
"type": "select-async",
"dependent_on": "category_id"
}
],
"apis": {
"categories": {
"filter": "your_plugin_get_categories",
"response_type": "select_options",
"target_fields": ["category_id"],
"dependencies": []
},
"items": {
"filter": "your_plugin_get_items",
"response_type": "select_options",
"target_fields": ["item_id"],
"dependencies": ["category_id"]
}
}
}PHP filter implementation:
add_filter( 'srfm_your_plugin_get_items', function( options, parameters ) {
category_id = parameters['category_id'] ?? '';
if ( empty( $category_id ) ) {
return [];
}
items = YourPlugin::get_items_by_category( category_id );
$formatted_options = [];
foreach ( items as item ) {
$formatted_options[] = [
'label' => $item->name,
'value' => $item->id,
];
}
return $formatted_options;
}, 10, 2 );
Multiple Actions
Add multiple actions to a single integration:
{
"actions": [
{
"name": "Create Customer",
"handler": {
"type": "action",
"action": "your_plugin_create_customer"
}
},
{
"name": "Create Order",
"handler": {
"type": "action",
"action": "your_plugin_create_order"
}
}
]
}
Each action requires its own PHP class:
- actions/create-order.php
- actions/create-customer.php
Error Handling
WordPress actions should return standardized results:
// Success result
return [
'success' => true,
'message' => __( 'Operation completed successfully!', 'sureforms-pro' ),
'data' => $additional_data, // Optional
];
// Error result using WP_Error
return new \WP_Error(
'operation_failed',
__( 'Operation failed: Error details', 'sureforms-pro' )
);
WordPress Hook Integration
Actions can trigger WordPress hooks for ecosystem integration:
protected function execute( $data ) {
// Execute business logic
result = $this->create_record( data );
// Fire WordPress hooks for other plugins
do_action( 'your_plugin_record_created', result, data );
do_action( 'your_plugin_sureforms_integration_executed', this->action, result );
return $result;
}
Complete Example
Directory Structure
inc/pro/native-integrations/integrations/latepoint/
├── config.json
├── actions.php
└── actions/
└── create-customer.php
config.json
{
"id": "latepoint",
"integration": {
"name": "LatePoint",
"icon": "latepoint.svg",
"website_url": "https://latepoint.com",
"docs_url": "https://latepoint.com/documentation/",
"category": "Booking & Appointments",
"description": "Create bookings and manage appointments in LatePoint booking system"
},
"provider": "wordpress",
"plugin_detection": {
"class": "OsBookingModel"
},
"auth": {
"type": "plugin_detection",
"test_endpoint": {
"method": "plugin_check",
"success_criteria": {
"plugin_active": true
}
}
},
"actions": [
{
"name": "Create Customer",
"description": "Create a new customer in LatePoint",
"provider": "wordpress",
"handler": {
"type": "action",
"action": "latepoint_create_customer"
},
"fields": [
{
"key": "first_name",
"label": "First Name",
"type": "text",
"required": true,
"placeholder": "John",
"description": "Customer's first name"
},
{
"key": "last_name",
"label": "Last Name",
"type": "text",
"required": true,
"placeholder": "Doe",
"description": "Customer's last name"
},
{
"key": "email",
"label": "Email",
"type": "email",
"required": true,
"placeholder": "[email protected]",
"description": "Customer's email address"
}
],
"apis": {
"customer_fields": {
"filter": "latepoint_get_customer_fields",
"response_type": "dynamic_fields",
"dependencies": []
}
}
}
]
}
actions.php
<?php
namespace SRFM_Pro\Inc\Pro\Native_Integrations\Integrations\LatePoint;
use SRFM_Pro\Inc\Traits\Get_Instance;
class LatePoint_Integration {
use Get_Instance;
public function __construct() {
$this->register_filters();
}
public function get_customer_custom_fields( $fields = [] ) {
if ( ! $this->is_plugin_active() ) {
return $fields;
}
// Get LatePoint custom fields from database
global $wpdb;
customer_fields = wpdb->get_row(
$wpdb->prepare(
"SELECT * FROM {$wpdb->prefix}latepoint_settings WHERE name = %s",
'custom_fields_for_customer'
)
);
// Format fields for SureForms
$formatted_fields = [];
if ( ! empty( customer_fields ) && ! empty( customer_fields->value ) ) {
custom_fields_data = json_decode( customer_fields->value, true );
if ( is_array( $custom_fields_data ) ) {
foreach ( custom_fields_data as field ) {
$formatted_fields[] = [
'key' => $field['id'],
'label' => field['label'] ?? ucwords( str_replace( '_', ' ', field['id'] ) ),
'type' => $field['type'] ?? 'text',
'required' => ! empty( $field['required'] ),
'description' => $field['placeholder'] ?? '',
];
}
}
}
return $formatted_fields;
}
private function is_plugin_active() {
return class_exists( 'OsCustomerModel' );
}
private function register_filters() {
if ( ! $this->is_plugin_active() ) {
return;
}
add_filter( 'srfm_latepoint_get_customer_fields', [ $this, 'get_customer_custom_fields' ] );
$this->load_action_files();
}
private function load_action_files() {
require_once __DIR__ . '/actions/create-customer.php';
}
}
LatePoint_Integration::get_instance();actions/create-customer.php
<?php
namespace SRFM_Pro\Inc\Pro\Native_Integrations\Integrations\LatePoint\Actions;
use SRFM_Pro\Inc\Pro\Native_Integrations\WordPress_Action;
use SRFM_Pro\Inc\Traits\Get_Instance;
class Create_Customer extends WordPress_Action {
use Get_Instance;
protected $integration = 'LatePoint';
protected $action = 'create_customer';
protected function is_plugin_active() {
return class_exists( 'OsCustomerModel' );
}
protected function execute( $data ) {
// Handle test mode
is_test_mode = isset( $data['_test_mode'] ) && true === data['_test_mode'];
if ( $is_test_mode ) {
unset( $data['_test_mode'] );
data['admin_notes'] = ( data['admin_notes'] ?? '' ) . "\n\n[TEST CUSTOMER - Created by SureForms workflow test]";
}
// Validate required fields
$required_fields = [ 'first_name', 'last_name', 'email' ];
validation = $this->validate_required_fields( $data, required_fields );
if ( is_wp_error( $validation ) ) {
return $validation;
}
try {
// Check if customer exists
$customer_model = new \OsCustomerModel();
existing_customer = $customer_model->where( [ 'email' => data['email'] ] )->set_limit( 1 )->get_results_as_models();
if ( ! empty( $existing_customer ) ) {
// Update existing customer
$existing_customer->set_data([
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'phone' => data['phone'] ?? existing_customer->phone,
'admin_notes' => data['admin_notes'] ?? existing_customer->admin_notes ?? '',
]);
if ( ! $existing_customer->save() ) {
throw new \Exception( 'Failed to update customer.' );
}
do_action( 'latepoint_customer_updated', $existing_customer );
return [
'success' => true,
'message' => __( 'Customer updated successfully!', 'sureforms-pro' ),
'customer_id' => $existing_customer->id,
'is_new' => false,
];
}
// Create new customer
$customer = new \OsCustomerModel();
$customer->set_data([
'first_name' => $data['first_name'],
'last_name' => $data['last_name'],
'email' => $data['email'],
'phone' => $data['phone'] ?? '',
'admin_notes' => $data['admin_notes'] ?? '',
'status' => 'active',
]);
if ( ! $customer->save() ) {
throw new \Exception( 'Failed to create customer.' );
}
do_action( 'latepoint_customer_created', $customer );
return [
'success' => true,
'message' => __( 'Customer created successfully!', 'sureforms-pro' ),
'customer_id' => $customer->id,
'is_new' => true,
];
} catch ( \Exception $e ) {
return new \WP_Error(
'customer_creation_failed',
sprintf(
__( 'Customer creation failed: %s', 'sureforms-pro' ),
$e->getMessage()
)
);
}
}
}
Create_Customer::get_instance();Common Integration Patterns
Plugin Detection
Always use the main plugin class for detection:
{
"plugin_detection": {
"class": "MainPluginClass"
}
}
Filter Naming Convention
Use consistent filter naming:
// Pattern: srfm_{plugin_name}_{action_type}_{object_type}
add_filter( 'srfm_latepoint_get_customer_fields', $callback );
add_filter( 'srfm_woocommerce_get_product_categories', $callback );
add_filter( 'srfm_gravity_get_form_fields', $callback );Action Naming Convention
Use consistent action naming:
{
"handler": {
"type": "action",
"action": "plugin_name_action_name"
}
}This creates WordPress action: srfm_plugin_name_action_name
Test Mode Implementation
Always support test mode in your actions:
protected function execute( $data ) {
is_test_mode = isset( $data['_test_mode'] ) && true === data['_test_mode'];
if ( $is_test_mode ) {
unset( $data['_test_mode'] );
// Add test identifiers as needed
}
// Execute real operations - no simulation
// Test mode creates real data for verification
}Troubleshooting
Common Issues
- Plugin Not Detected
- Verify plugin_detection.class exists
- Check plugin activation status
- Ensure class name is correct
- Actions Not Executing
- Verify action file is loaded
- Check WordPress action hook registration
- Confirm get_instance() is called
- Dynamic Fields Not Loading
- Verify filter name matches JSON configuration
- Check filter callback registration
- Ensure plugin is active when filter runs
- Test Workflow Fails
- Check required field validation
- Verify plugin classes are available
- Review error messages in developer tools
Debugging Tips
// Add debug logging to your actions
protected function execute( $data ) {
error_log( 'SureForms Action: ' . this->integration . '_' . this->action );
error_log( 'Data: ' . print_r( $data, true ) );
// Your execution logic
}
// Add debug logging to filters
add_filter( 'srfm_your_plugin_get_fields', function( $fields ) {
error_log( 'SureForms Filter: fields requested' );
error_log( 'Fields: ' . print_r( $fields, true ) );
return $fields;
});
This guide provides a comprehensive foundation for creating WordPress plugin integrations with SureForms Pro. The system is designed to be flexible while maintaining consistency and reliability across different plugin ecosystems.
We don't respond to the article feedback, we use it to improve our support content.