A professional WordPress plugin for cybersecurity penetration test quote requests with multi-step form, Salesforce integration, webhook/API integrations, and full customization options.
- Features
- Requirements
- Installation
- Quick Start
- Shortcode Usage
- Settings Panel
- Question & Category Management
- Customizing Form Labels
- Typography Settings
- Salesforce Integration
- Webhook Integrations
- Managing Submissions
- Security
- Style Customization
- Troubleshooting
- FAQ
- Technical Reference
- Changelog
- Contributing
- License
| Feature | Description |
|---|---|
| π Multi-Step Form | 3-step form with animated progress indicator |
| π― Popup & Inline | Both popup modal and embedded form support |
| π Dynamic Questions | Category-based question management with drag & drop |
| π± Mobile Responsive | Fully responsive design for all devices |
| β GDPR Compliant | Built-in privacy consent mechanism |
| Feature | Description |
|---|---|
| βοΈ Salesforce | Direct Lead/Contact/Opportunity creation via REST API or Web-to-Lead |
| π Webhooks | Power Automate, Zapier, Make, custom API support |
| π§ Email | Automatic notifications and auto-reply emails |
| Feature | Description |
|---|---|
| π External Client App | Modern Client Credentials OAuth flow (recommended) |
| π Web-to-Lead | Easiest setup β no Connected App required, just Organization ID |
| π Legacy Support | Password Grant flow for backward compatibility |
| π§ͺ Connection Testing | Test button to verify integration before going live |
| π Activity Log | Real-time log of last 20 Salesforce events |
| πΊοΈ Field Mapping | JSON-based field mapping with custom fields support |
| π My Domain Support | Custom Salesforce domain URL support |
| Feature | Description |
|---|---|
| π‘οΈ reCAPTCHA v3 | Google reCAPTCHA bot protection |
| π’ Corporate Email Filter | Blocks 50+ personal email providers |
| π¨ Full Customization | Colors, fonts, labels, messages |
| π€ Typography | 8 Google Fonts + system + custom fonts |
| π CSV Export | Export all submissions to CSV |
- WordPress 5.0 or higher
- PHP 7.2 or higher
- MySQL 5.6 or higher
- Download the latest release from Releases
- WordPress Admin β Plugins β Add New β Upload Plugin
- Upload the ZIP file and click Activate
- Upload the
pentest-quote-formfolder to/wp-content/plugins/ - Activate from WordPress Admin β Plugins
cd /wp-content/plugins/
git clone https://github.com/lostarus/Wordpress-MultiPage-Form.git pentest-quote-form- Go to WordPress Admin β Quote Requests β Settings
- Enter your notification email address
- Add shortcode to any page:
- Popup button:
[ptf_popup_trigger] - Inline form:
[ptf_multistep_form]
- Popup button:
[ptf_popup_trigger]
[ptf_popup_trigger text="Get Quote"]
[ptf_popup_trigger text="Request Quote" class="my-btn" primary="#E74C3C"]
| Parameter | Default | Description |
|---|---|---|
text |
"Get Quick Quote" | Button text |
class |
- | Additional CSS class |
primary |
#2F7CFF | Primary/background color |
secondary |
#B7FF10 | Secondary color |
size |
medium | small, medium, large, xlarge, custom |
padding_y |
- | Custom vertical padding (px) |
padding_x |
- | Custom horizontal padding (px) |
font_size |
- | Custom font size (px) |
[ptf_popup_trigger size="small"]
[ptf_popup_trigger size="xlarge" text="Get Your Quote Now"]
[ptf_popup_trigger padding_y="20" padding_x="50" font_size="18"]
| Size | Padding | Font |
|---|---|---|
| small | 12px 24px | 14px |
| medium | 16px 32px | 16px |
| large | 20px 40px | 18px |
| xlarge | 24px 48px | 20px |
[ptf_multistep_form]
[ptf_multistep_form primary="#9B59B6" secondary="#F1C40F"]
Access settings from WordPress Admin β Quote Requests β Settings.
| Setting | Description |
|---|---|
| Notification Email | Receives form submissions (comma-separated for multiple) |
| Auto Reply | Sends confirmation to submitter |
| Setting | Description |
|---|---|
| Save to Database | Stores submissions in WordPress database |
| Send Email | Sends email notification per submission |
β οΈ At least one option must be active!
| Setting | Default | Usage |
|---|---|---|
| Primary Color | #2F7CFF | Buttons, active elements |
| Secondary Color | #B7FF10 | Success icons |
| Button Text Color | #FFFFFF | Popup trigger button text |
| Preset | Description |
|---|---|
| Small | Compact (12px 24px, 14px font) |
| Medium | Default (16px 32px, 16px font) |
| Large | Larger (20px 40px, 18px font) |
| Extra Large | Biggest (24px 48px, 20px font) |
| Custom (px) | Define your own values |
| Setting | Example |
|---|---|
| Privacy Notice URL | /privacy-notice |
| Privacy Policy URL | /privacy-policy |
Manage from WordPress Admin β Quote Requests β Questions.
- Click Add New Category
- Enter name, ID (lowercase with hyphens), and icon (emoji)
- Activate/deactivate as needed
| Type | Description | Use Case |
|---|---|---|
| text | Single line | Short answers |
| textarea | Multi-line | Long descriptions |
| number | Numeric | Quantities |
| select | Dropdown | Single selection |
| radio | Radio buttons | Single selection (visible) |
| checkbox | Checkboxes | Multiple selection |
| date | Date picker | Dates |
| Email field | Email validation | |
| tel | Phone field | Phone numbers |
For select, radio, checkbox types:
Option Label|option_value
Yes|yes
No|no
Customize all texts from Settings β Form Labels & Texts.
| Field | Default |
|---|---|
| Form Title | Get Quick Quote |
| Form Subtitle | Get a quote for your cybersecurity needs |
| Step | Default |
|---|---|
| Step 1 | Test Selection |
| Step 2 | Test Details |
| Step 3 | Contact Information |
| Field | Label | Placeholder |
|---|---|---|
| Company | Company Name | Company name |
| Contact | Contact Person | Your Full Name |
| corporate@yourcompany.com | ||
| Phone | Phone | +1 555 XXX XXXX |
| Button | Default |
|---|---|
| Next | Continue |
| Back | Back |
| Submit | Submit |
| Message | Default |
|---|---|
| Required | This field is required. |
| Invalid Email | Please enter a valid email address. |
| Corporate Email | Please enter your corporate email address... |
| Invalid Phone | Please enter a valid phone number. |
| reCAPTCHA Error | reCAPTCHA verification failed... |
Customize fonts from Settings β Color Settings β Typography.
| Font | Description |
|---|---|
| Inherit | Uses theme's font |
| System UI | San Francisco, Segoe UI |
| Inter | Modern sans-serif (Google) |
| Roboto | Clean sans-serif (Google) |
| Open Sans | Humanist sans-serif (Google) |
| Lato | Warm sans-serif (Google) |
| Poppins | Geometric sans-serif (Google) |
| Montserrat | Urban sans-serif (Google) |
| Nunito | Rounded sans-serif (Google) |
| Custom | Your own font-family CSS |
| Element | Range | Default |
|---|---|---|
| Headings | 14-48 px | 26 px |
| Body Text | 10-24 px | 15 px |
| Labels | 10-20 px | 14 px |
Send form submissions directly to Salesforce as a Lead, Contact, Account, Opportunity, or Case β no third-party middleware required.
The plugin supports three integration methods:
- Web-to-Lead (Easiest) β No Connected App or OAuth required. Just enter your Organization ID (OID). Creates Lead records only.
- Client Credentials Flow (Recommended for API) β Uses the new Salesforce External Client App structure. No username/password required. Supports Lead, Contact, Account, Opportunity, Case.
- Password Grant Flow (Legacy) β Uses the traditional Connected App with username/password. Deprecated but supported for backward compatibility.
An access token is cached for 50 minutes and automatically refreshed when it expires (Client Credentials and Password Grant flows only).
The simplest way to send leads to Salesforce. No Connected App, no OAuth, no API credentials needed.
What You Need:
- Your Salesforce Organization ID (OID) β starts with
00D
How to Find Your OID:
- Method A: Go to Setup β Company Information β Organization ID
- Method B: Go to Setup β Web-to-Lead β Create Web-to-Lead Form
- Select the fields you want (First Name, Last Name, Email, Company, Description, etc.)
- Enter any Return URL (e.g.,
https://yoursite.com) - Click Generate
- In the generated HTML, find:
<input type="hidden" name="oid" value="00Dxxxxxxxxxx"> - Copy the
valueβ that's your OID
Limitations:
| Limitation | Details |
|---|---|
| Lead only | Cannot create Contact, Account, Opportunity, or Case |
| No feedback | "Fire and forget" β no success/error confirmation from Salesforce |
| Daily limit | 500 leads/day (default Salesforce limit) |
| No validation | Salesforce validation rules won't return error messages |
| No connection test | Cannot test the connection β only verify via checking Salesforce for new leads |
Tip: Web-to-Lead is ideal for simple lead capture scenarios. If you need error feedback, custom objects, or advanced field mapping, use Client Credentials flow instead.
This is the modern, secure way to integrate with Salesforce. No username/password required.
Step-by-Step Setup in Salesforce:
-
Log in to your Salesforce org
-
Go to Setup (gear icon β Setup)
-
In Quick Find, search for "External Client App Manager"
-
Click "New External Client App"
-
Fill in basic information:
- App Name:
WordPress Form Integration - API Name:
WordPress_Form_Integration - Contact Email: Your email address
- Description: (optional) WordPress form integration
- App Name:
-
Under OAuth Settings:
- Check Enable OAuth Settings
- Callback URL:
https://yoursite.com(any valid URL, not actually used for Client Credentials) - β Check Enable Client Credentials Flow
- Selected OAuth Scopes: Add these:
Manage user data via APIs (api)Perform requests at any time (refresh_token, offline_access)
-
Click Save and wait 2-10 minutes for activation
-
Get Consumer Key and Secret:
- In External Client App Manager, find your app
- Click on your app name to open it
- Look for OAuth Settings or App Credentials section
- Click Manage Consumer Details or similar
- Verify your identity (Salesforce will send a verification code)
- Copy the Consumer Key and Consumer Secret
-
β οΈ CRITICAL - Set Run As User:- In External Client App Manager, find your app
- Click the dropdown arrow (βΌ) next to your app β Manage
- Click Edit Policies
- Scroll to Client Credentials Flow section
- Select a Run As user from the dropdown
- This user's permissions will be used for all API calls
- Choose a user with API access (System Administrator or Integration User)
- Optionally, under IP Relaxation, select "Relax IP restrictions"
- Click Save
β οΈ Most Common Error: "request not supported on this domain" means the Run As user is NOT set. Step 9 is mandatory!
Required from Salesforce:
- Consumer Key (Client ID)
- Consumer Secret
- A Run As user configured in App Policies
Where to Find Things:
| Item | Location in Salesforce Setup |
|---|---|
| Create/View App | Setup β External Client App Manager |
| Consumer Key/Secret | Your App β Manage Consumer Details |
| Run As User | Your App β Manage β Edit Policies β Client Credentials Flow |
- A Salesforce org (Production or Sandbox)
- A Connected App with OAuth enabled (How to create one)
- Enable OAuth Settings β check Enable OAuth
- Add any Callback URL (e.g.
https://yoursite.com) - Scopes: api, refresh_token
- Important: Set IP policy to Relax IP Restrictions under Manage β Edit Policies
- Your Salesforce username, password, and security token
- Get security token: Setup β My Personal Information β Reset My Security Token
- Go to WordPress Admin β Quote Requests β Settings
- Scroll to Salesforce Direct Integration
- Check Enable Salesforce Integration
- Select your Integration Method:
| Field | Description |
|---|---|
| Integration Method | Select "Web-to-Lead (No App Required - Easiest)" |
| Organization ID (OID) | Your Salesforce Organization ID (starts with 00D) |
Web-to-Lead Field Mapping:
{
"last_name": "first_name",
"email": "email",
"phone": "phone",
"company": "company",
"description": "target_scope_text",
"lead_source": "__static:Web"
}The left key is the Salesforce Web-to-Lead field name (lowercase, as shown in the generated HTML). The right value is the form field name. Use __static:VALUE for fixed values.
Available Web-to-Lead Field Names:
| W2L Field | Description |
|---|---|
first_name |
First Name |
last_name |
Last Name |
email |
|
phone |
Phone |
company |
Company |
title |
Title |
city |
City |
state / state_code |
State/Province (text / dropdown) |
country / country_code |
Country (text / dropdown) |
zip |
Zip Code |
street |
Street Address |
description |
Description |
lead_source |
Lead Source |
industry |
Industry |
URL |
Website |
00NXX000000XXXXX |
Custom field ID |
Note: Use
state_code/country_codeif you selected the dropdown versions in Salesforce Web-to-Lead setup, orstate/countryfor the text-only versions.
| Field | Description |
|---|---|
| OAuth Flow | Select "Client Credentials (External Client App - Recommended)" |
| Login URL / My Domain | https://yourcompany.my.salesforce.com (Find it in Salesforce Setup β My Domain) |
| Consumer Key | From your External Client App β OAuth Settings |
| Consumer Secret | From your External Client App β OAuth Settings |
| Salesforce Object | Lead (default), Contact, Account, Opportunity, or Case |
| API Version | Default v59.0 β match your org's API version if needed |
β οΈ Important: For Client Credentials flow, you should use your My Domain URL (e.g.,https://yourcompany.my.salesforce.com) instead oflogin.salesforce.com. Using the generic login URL often results in "request not supported on this domain" error.
| Field | Description |
|---|---|
| OAuth Flow | Select "Password Grant (Legacy Connected App)" |
| Login URL | https://login.salesforce.com (Production) or https://test.salesforce.com (Sandbox) |
| Consumer Key | From your Connected App β OAuth Settings |
| Consumer Secret | From your Connected App β OAuth Settings |
| Username | Your Salesforce login email |
| Password + Security Token | Password concatenated with security token, no spaces (e.g. MyPassword1ABC123xyz) |
| Salesforce Object | Lead (default), Contact, Account, Opportunity, or Case |
| API Version | Default v59.0 β match your org's API version if needed |
- Configure Field Mapping (JSON editor):
{
"Company": "company",
"LastName": "first_name",
"Email": "email",
"Phone": "phone",
"Description": "test_types_text"
}The left key is the Salesforce API field name; the right value is the form field name.
| Form Field | Description |
|---|---|
first_name |
Contact person name |
email |
Email address |
phone |
Phone number |
company |
Company name |
test_types_text |
Readable list of selected test types (comma-separated) |
target_scope_text |
All question-answers as readable plain text |
answers_json |
All question-answers as structured JSON |
submitted_at |
Submission date/time |
page_url |
URL of the page where the form was submitted |
kvkk_consent |
Privacy consent status (1 or 0) |
| (dynamic question IDs) | Any custom question field key (visible in admin "Available Form Fields" box) |
Note: When the target object is
Lead,LeadSourceis automatically set to"Web"if not mapped.Tip: Click "Show/Hide" under Available Form Fields in the admin panel to see all available field names including dynamic question IDs.
Below are common mapping configurations for different use cases.
Send contact info and selected test types:
{
"Company": "company",
"LastName": "first_name",
"Email": "email",
"Phone": "phone",
"Description": "test_types_text"
}Description will contain: Web Application Penetration Test, API Security Test
Send all question-answers in a readable text format to the Description field:
{
"Company": "company",
"LastName": "first_name",
"Email": "email",
"Phone": "phone",
"Description": "target_scope_text"
}Description will contain:
=== Web Application Penetration Test ===
How many pages?: 50
Framework?: React
=== API Security Test ===
Number of endpoints?: 20
Authentication type?: OAuth 2.0
Send all question-answers as structured JSON for programmatic processing:
{
"Company": "company",
"LastName": "first_name",
"Email": "email",
"Phone": "phone",
"Description": "answers_json"
}Description will contain:
[
{
"category": "Web Application Penetration Test",
"questions": [
{ "question": "How many pages?", "answer": "50" },
{ "question": "Framework?", "answer": "React" }
]
},
{
"category": "API Security Test",
"questions": [
{ "question": "Number of endpoints?", "answer": "20" }
]
}
]Map specific question answers to custom Salesforce fields:
{
"Company": "company",
"LastName": "first_name",
"Email": "email",
"Phone": "phone",
"NumberOfPages__c": "q_page_count",
"Framework__c": "q_framework",
"Description": "test_types_text"
}Use the dynamic question field IDs from the "Available Form Fields" reference box in the admin panel.
Combine test types and full answers into Description, map individual fields to custom Salesforce fields:
{
"Company": "company",
"LastName": "first_name",
"Email": "email",
"Phone": "phone",
"Website": "page_url",
"Description": "target_scope_text",
"NumberOfPages__c": "q_page_count"
}If you're currently using the Password Grant flow and want to migrate to the recommended Client Credentials flow:
- Create a new External Client App in Salesforce Setup
- Enable Client Credentials Flow and set a Run As user
- Copy the new Consumer Key and Consumer Secret
- In WordPress settings, change OAuth Flow to "Client Credentials"
- Update the Consumer Key and Consumer Secret
- Save settings - username/password fields will be ignored
Note: Connection testing is only available for Client Credentials and Password Grant flows. Web-to-Lead is "fire and forget" and cannot be tested β verify by checking your Salesforce org for new leads after a form submission.
After configuring your Salesforce credentials (Client Credentials or Password Grant):
- Click the Test Connection button in the Salesforce settings section
- The plugin will attempt to:
- Authenticate with Salesforce using your credentials
- Access the Salesforce REST API
- Describe the target object (Lead, Contact, etc.)
- On success, you'll see:
- β Instance URL confirmation
- Number of available fields
- List of required fields for the object
- On failure, you'll see:
- β Which step failed (Authentication or API Access)
- Detailed error message for troubleshooting
The plugin maintains an activity log of the last 20 Salesforce events:
| Log Entry | Description |
|---|---|
| β Success | Record created with Salesforce ID |
| β Error | Failed submission with error message |
Features:
- View timestamp for each event
- See Salesforce record IDs for successful submissions
- Expand "View Data" on errors to see the exact JSON that was sent
- Clear logs with one click
This helps you:
- Verify that submissions are reaching Salesforce
- Debug field mapping issues
- Identify authentication problems
- Track integration health over time
// Modify the Salesforce record before it is sent (REST API flows)
add_filter('ptf_salesforce_record', function($record, $form_data, $object) {
$record['LeadSource'] = 'Website';
$record['Rating'] = 'Hot';
return $record;
}, 10, 3);
// Fires after a Salesforce record is successfully created (REST API flows)
add_action('ptf_salesforce_record_created', function($sf_id, $form_data, $object) {
// $sf_id is the new Salesforce record ID
error_log('Salesforce record created: ' . $sf_id);
}, 10, 3);
// Modify Web-to-Lead data before it is sent
add_filter('ptf_salesforce_web_to_lead_data', function($w2l_data, $form_data) {
$w2l_data['campaign_id'] = '701xx000000XXXX'; // Assign to a campaign
return $w2l_data;
}, 10, 2);
// Fires after Web-to-Lead submission is sent
add_action('ptf_salesforce_web_to_lead_sent', function($w2l_data, $form_data) {
error_log('Web-to-Lead submitted for: ' . $w2l_data['email']);
}, 10, 2);| Problem | Solution |
|---|---|
| "request not supported on this domain" | Most likely cause: You need to use your My Domain URL. Go to Settings β Select "My Domain (Custom URL)" β Enter https://yourcompany.my.salesforce.com. Also ensure Run As user is set in External Client App Manager. |
| Authentication failed (Client Credentials) | 1) Use My Domain URL instead of login.salesforce.com 2) Ensure Run As user is assigned in Edit Policies |
| Authentication failed (Password Grant) | Double-check Consumer Key/Secret and that IP policy is set to Relax IP Restrictions |
| Invalid client | Consumer Key or Consumer Secret is wrong. Go to External Client App Manager β Your App β Manage Consumer Details |
| Invalid password | Make sure to append the security token directly to the password (Password Grant only) |
| INVALID_FIELD error | The mapped Salesforce field name is wrong or doesn't exist on the object |
| Required field missing | Lead requires LastName and Company β ensure they are mapped |
| Sandbox not working | Use your Sandbox My Domain URL: https://yourcompany--sandboxname.sandbox.my.salesforce.com |
| Check Activity Log | View the Activity Log in WordPress admin for detailed error messages and sent data |
| Check WordPress logs | Errors are also written to the WordPress debug log (WP_DEBUG_LOG) with prefix PTF Salesforce Error: |
Send form data to external systems automatically.
- Power Automate - Microsoft Flow
- Zapier - 5000+ app integrations
- Make (Integromat) - Visual automation
- Custom API - Any endpoint
- Go to Settings β Webhook / API Integrations
- Enable webhooks
- Click platform button or add custom webhook
- Enter Webhook URL
- Save
[
{
"name": "Power Automate",
"type": "power_automate",
"url": "https://prod-xx.westeurope.logic.azure.com/...",
"method": "POST",
"active": true
},
{
"name": "CRM API",
"type": "custom",
"url": "https://api.crm.com/v1/leads",
"method": "POST",
"auth_type": "bearer",
"auth_value": "your-token",
"active": true
}
]{
"meta": {
"source": "pentest-quote-form",
"version": "1.6.0",
"site_name": "Your Site",
"submitted_at": "2026-04-20 14:30:00"
},
"contact": {
"name": "John Smith",
"email": "john@company.com",
"phone": "+1 555 123 4567",
"company": "Company Inc."
},
"selected_categories": [...],
"answers": [...],
"flat": {...}
}View submissions from WordPress Admin β Quote Requests.
| Status | Description |
|---|---|
| π new | New submission |
| π contacted | Contact made |
| π° quoted | Quote sent |
| β completed | Completed |
Click Export as CSV to download all records.
- Get keys from Google reCAPTCHA
- Select reCAPTCHA v3
- Enter Site Key and Secret Key in Settings β reCAPTCHA
Automatically blocks personal emails:
- gmail.com, outlook.com, hotmail.com
- yahoo.com, yandex.com, icloud.com
- And 50+ other providers
- Maximum 5 submissions per IP per hour
- Automatic spam protection
- Localhost/internal IPs blocked for webhooks
- Only HTTPS/HTTP accepted
- Metadata endpoints blocked
[ptf_popup_trigger primary="#E74C3C" secondary="#2ECC71"]
[ptf_multistep_form primary="#9B59B6"]
/* Button style */
.ptf-popup-trigger {
border-radius: 8px !important;
}
/* Form container */
.ptf-form-wrapper {
box-shadow: 0 10px 40px rgba(0,0,0,0.15) !important;
}| Variable | Usage |
|---|---|
--ptf-primary |
Primary color |
--ptf-secondary |
Secondary color |
--ptf-button-text |
Button text color |
- Check shortcode syntax
- Check browser console for JS errors (F12)
- Test for theme/plugin conflicts
- Verify Send Email Notification is enabled
- Check WordPress email settings
- Use SMTP plugin (WP Mail SMTP)
- Verify URL is correct
- Use HTTPS
- Test with the test button
- Check WordPress error logs
- Deactivate plugin
- Reactivate
- Check for
wp_ptf_submissionstable
Q: Can I use multiple forms on one page? A: Yes, each form works independently.
Q: Where is data stored?
A: In wp_ptf_submissions table in WordPress database.
Q: Is it GDPR compliant? A: Yes, includes privacy consent, CSV export, and record deletion.
Q: Can I remove corporate email filter? A: Requires code modification.
pentest-quote-form/
βββ pentest-quote-form.php # Main plugin file
βββ uninstall.php # Clean uninstall handler
βββ README.md # This documentation
βββ CHANGELOG.md # Version history
βββ LICENSE # GPL v2 License
βββ CONTRIBUTING.md # Contribution guidelines
βββ SECURITY.md # Security policy
βββ CODE_OF_CONDUCT.md # Code of conduct
βββ assets/
β βββ css/
β β βββ admin-questions.css # Question management styles
β β βββ admin-settings.css # Settings page styles
β β βββ form-styles.css # Frontend form styles
β βββ js/
β βββ admin-questions.js # Question management scripts
β βββ admin-settings.js # Settings page scripts
β βββ admin-utils.js # Shared admin utilities
β βββ form-scripts.js # Frontend form scripts
βββ includes/
βββ class-form.php # Main form class & Salesforce integration
βββ class-form-admin.php # Admin submissions page
βββ class-form-questions.php # Question/category management
βββ class-form-settings.php # Settings management
// After successful form submission
do_action('ptf_after_submission', $form_data, $submission_id);
// Modify email content before sending
$content = apply_filters('ptf_email_content', $content, $form_data);
// Modify webhook payload before sending
$payload = apply_filters('ptf_webhook_payload', $payload, $form_data);
// Modify Salesforce record before sending
$record = apply_filters('ptf_salesforce_record', $record, $form_data, $sf_object);
// Fires after successful Salesforce record creation (REST API)
do_action('ptf_salesforce_record_created', $sf_id, $form_data, $sf_object);
// Modify Web-to-Lead data before sending
$w2l_data = apply_filters('ptf_salesforce_web_to_lead_data', $w2l_data, $form_data);
// Fires after Web-to-Lead submission is sent
do_action('ptf_salesforce_web_to_lead_sent', $w2l_data, $form_data);
// Modify blocked email domains list
$domains = apply_filters('ptf_blocked_email_domains', $domains);Submissions Table: wp_ptf_submissions
CREATE TABLE wp_ptf_submissions (
id bigint(20) AUTO_INCREMENT,
first_name varchar(255) NOT NULL,
last_name varchar(255) DEFAULT '',
email varchar(255) NOT NULL,
phone varchar(50) DEFAULT '',
company varchar(255) NOT NULL,
test_types text NOT NULL,
target_scope text NOT NULL,
kvkk_consent tinyint(1) DEFAULT 0,
page_url varchar(500) DEFAULT '',
user_ip varchar(45) DEFAULT '',
submitted_at datetime DEFAULT CURRENT_TIMESTAMP,
status varchar(20) DEFAULT 'new',
PRIMARY KEY (id)
);Questions Table: wp_ptf_questions
CREATE TABLE wp_ptf_questions (
id bigint(20) AUTO_INCREMENT,
option_key varchar(100) NOT NULL DEFAULT 'categories',
option_value longtext NOT NULL,
updated_at datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE KEY option_key (option_key)
);The plugin uses WordPress AJAX for form submission:
| Action | Endpoint | Description |
|---|---|---|
ptf_submit_form |
admin-ajax.php |
Form submission handler |
ptf_test_webhooks |
admin-ajax.php |
Webhook testing |
ptf_test_salesforce |
admin-ajax.php |
Salesforce connection test |
ptf_save_questions |
admin-ajax.php |
Save questions/categories |
- β¨ Added: Salesforce Web-to-Lead integration β no Connected App or OAuth required, just Organization ID
- β¨ Added: Configurable Web-to-Lead field mapping with JSON editor and
__static:prefix for fixed values - β¨ Added: Web-to-Lead reference boxes showing all available Salesforce W2L and form field names
- β¨ Added: Developer hooks
ptf_salesforce_web_to_lead_data(filter) andptf_salesforce_web_to_lead_sent(action) - β Fixed: Settings preservation on plugin update β settings no longer lost when plugin is updated
- β Fixed: Double-sanitization bug that caused field mapping and checkbox values to revert on first save
- β Fixed: Webhooks no longer wiped when invalid JSON is submitted
- π§ Improved: Settings sanitization starts from saved values instead of empty array
- β¨ Added:
target_scope_textfield β all question-answers as readable plain text for Salesforce mapping - β¨ Added:
answers_jsonfield β all question-answers as structured JSON for Salesforce mapping - β¨ Added: New field mapping scenarios documentation with usage examples
- π§ Improved: Available Form Fields reference now includes all mappable answer fields
- π§ Improved: reCAPTCHA is now truly optional β form works without any reCAPTCHA configuration
- β¨ Added: Interactive form fields reference box with click-to-copy
- β¨ Added: Dynamic question fields auto-listed in reference
- π§ Improved: Salesforce mapping UX with field descriptions
- β Fixed: Salesforce field mapping JSON persistence after page reload
- β
Fixed: JSON parsing with
wp_unslash()for WordPress compatibility
- β Fixed: Content-Type header for Salesforce OAuth requests
- β Fixed: Custom My Domain URLs now persist after save
- β Fixed: Client Credentials flow works with My Domain
- β¨ Added: Salesforce External Client App support (Client Credentials flow)
- β¨ Added: Test Connection button for Salesforce
- β¨ Added: Activity Log for Salesforce events
- β¨ Added: My Domain URL support
- π§ Improved: Error messages with original Salesforce responses
- β¨ Added: Typography settings (8 Google Fonts)
- β¨ Added: Form header customization
- β¨ Added: Validation messages customization
- β¨ Added: Button text color and size options
- β¨ Added: Live preview in admin
- β¨ Added: Customizable form labels and texts
- β¨ Added: Comprehensive documentation
- π Initial public release
See CHANGELOG.md for full version history.
This project is licensed under the GPL v2 or later. See LICENSE for details.
Pentest Quote Form - WordPress Plugin
Copyright (C) 2026 mustafaer
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
Contributions are welcome! Please read our Contributing Guide for details.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
# Clone the repository
git clone https://github.com/lostarus/Wordpress-MultiPage-Form.git
# Navigate to your WordPress plugins directory
mv Wordpress-MultiPage-Form /path/to/wordpress/wp-content/plugins/pentest-quote-form
# Activate the plugin in WordPress admin- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Changelog: CHANGELOG.md
- Security: SECURITY.md
mustafaer - GitHub
If you find this plugin useful, please consider:
- Giving it a β star on GitHub
- Sharing it with others
- Contributing to the project
Pentest Quote Form
Professional WordPress plugin for cybersecurity penetration test quote forms.
Download Latest Release
Β·
Report Bug
Β·
Request Feature