Campaign management for customer surveys with SMS and email invitations for Craft CMS 5.x.
This plugin is currently in active development and provided under the MIT License for testing purposes.
Licensing is subject to change. We are finalizing our licensing structure and some or all features may require a paid license when officially released on the Craft Plugin Store.
- Campaign Management: Create and manage survey campaigns linked to Formie forms
- Multi-site support with site-specific customers
- Campaign types for organization
- Configurable invitation delay and expiry periods
- Customer Management:
- Import customers from CSV files
- Add individual customers manually
- Track invitation status (sent, opened, submitted)
- Unique invitation codes per customer
- Export customers to CSV/JSON
- Multi-Channel Invitations:
- SMS invitations via SMS Manager
- Email invitations with customizable templates
- Bitly URL shortening for SMS links
- Queue-Based Processing:
- Batch processing for large customer lists
- Background job execution
- Progress tracking
- Survey Response Tracking:
- Link Formie submissions to customers
- Track survey completion rates
- Invitation expiry handling
- Comprehensive Analytics:
- Customer counts per campaign
- Submission tracking
- Date range filtering
- User Permissions: Granular access control for campaigns, customers, and settings
- Logging: Structured logging via Logging Library with configurable levels
- Craft CMS 5.0 or greater
- PHP 8.2 or greater
- Formie 3.0 or greater
- SMS Manager 5.0 or greater (for SMS invitations)
- Logging Library 5.0 or greater (installed automatically)
- Plugin Base 5.0 or greater (installed automatically)
Until published on Packagist, install directly from the repository:
cd /path/to/project
composer config repositories.survey-campaigns vcs https://github.com/LindemannRock/craft-survey-campaigns
composer require lindemannrock/craft-survey-campaigns:dev-main
./craft plugin/install formie-campaignsOnce published on Packagist:
cd /path/to/project
composer require lindemannrock/craft-survey-campaigns
./craft plugin/install formie-campaigns- Go to the Plugin Store in your Craft control panel
- Search for "Survey Campaigns"
- Click "Install"
Navigate to Survey Campaigns → Settings in the control panel to configure:
General Settings:
- Plugin Name: Customize the display name in the control panel
- Campaign Section Handle: The section handle where campaigns are stored
Bitly Settings:
- Bitly API Key: API key for URL shortening (environment variable recommended)
Logging Settings:
- Log Level: debug, info, warning, error
# .env
BITLY_API_KEY=your-bitly-api-keyCreate a config/formie-campaigns.php file to override default settings:
<?php
return [
// Plugin Settings
'pluginName' => 'Survey Campaigns',
'campaignSectionHandle' => 'campaigns',
// Logging Settings
'logLevel' => 'error',
// Multi-environment support
'dev' => [
'logLevel' => 'debug',
],
'production' => [
'logLevel' => 'error',
],
];Create a Craft section for campaigns with the following fields:
- Campaign Type (Dropdown): Type categorization
- Form (Formie Form): The survey form
- Invitation Delay Period (Text): ISO 8601 duration (e.g.,
P1Dfor 1 day) - Invitation Expiry Period (Text): ISO 8601 duration (e.g.,
P30Dfor 30 days) - SMS Invitation Message (Plain Text): SMS template with
{survey_link}and{customer_name}tokens - Email Invitation Subject (Plain Text): Email subject line
- Email Invitation Message (Rich Text): Email template with tokens
- Sender ID (Text): SMS sender ID handle
- Surveys Welcome (Rich Text): Message shown before survey
- Surveys Already Responded (Rich Text): Message for completed surveys
- Surveys Invitation Expired (Rich Text): Message for expired invitations
- Navigate to Survey Campaigns → Settings
- Set the Campaign Section Handle to match your section
- Configure Bitly API key if using SMS invitations
Create a template for the survey page (e.g., templates/survey.twig):
{% extends '_layouts/surveys.twig' %}
{% block content %}
{% set invitationCode = craft.app.request.getQueryParam('invitationCode') %}
{% if invitationCode %}
{% set customer = formieCampaigns.customers.getCustomerByInvitationCode(invitationCode) %}
{% set campaign = customer.getCampaign() %}
{% if customer.hasSubmission() %}
{{ campaign.surveysAlreadyResponded|raw }}
{% elseif customer.invitationIsExpired() %}
{{ campaign.surveysInvitationExpired|raw }}
{% else %}
{{ campaign.surveysWelcome|raw }}
{{ craft.formie.renderForm(campaign.getForm()) }}
{% endif %}
{% else %}
<p>Invalid invitation code.</p>
{% endif %}
{% endblock %}- Navigate to Survey Campaigns in the control panel
- Click New Campaign to create a campaign entry
- Configure the campaign settings and associated form
- Save the campaign
- Navigate to the campaign's customer list
- Click Add → New Customer
- Enter customer details (name, email, phone, site)
- Save
- Navigate to the campaign's customer list
- Click Add → Import from CSV
- Upload a CSV file with columns:
Name(required)Email(optional)Phone(optional)Language(optional:enorar)
- Choose whether to send invitations after import
- Click Import
CSV Format Example:
Name,Email,Phone,Language
John Doe,john@example.com,96512345678,en
Ahmed Ali,ahmed@example.com,96598765432,ar- Navigate to the campaign's customer list
- Click Run Campaign
- Invitations will be queued and sent in batches
- Navigate to Survey Campaigns
- Click Run All
- All campaigns will be processed
- Navigate to the campaign's customer list
- Click Export
- Choose format (CSV or JSON)
- Download includes all customer data and status
{# Get all campaigns #}
{% set campaigns = formieCampaigns.campaigns.find().all() %}
{# Get campaign by ID #}
{% set campaign = formieCampaigns.campaigns.find().id(123).one() %}
{# Get campaigns for a site #}
{% set campaigns = formieCampaigns.campaigns.find().site('en').all() %}{# Get customer by invitation code #}
{% set customer = formieCampaigns.customers.getCustomerByInvitationCode(code) %}
{# Mark customer as opened #}
{% do formieCampaigns.customers.markAsOpened(customer) %}
{# Check customer status #}
{% if customer.hasSubmission() %}
{# Already submitted #}
{% elseif customer.invitationIsExpired() %}
{# Invitation expired #}
{% endif %}# Run all campaigns
./craft formie-campaigns/campaigns/run-all
# Run specific campaign
./craft formie-campaigns/campaigns/run --campaign=123- Manage campaigns
- View campaigns
- Create campaigns
- Edit campaigns
- Delete campaigns
- Manage customers
- View customers
- Create customers
- Import customers
- Delete customers
- Export customers
- Manage settings
use lindemannrock\surveycampaigns\services\CustomersService;
use lindemannrock\surveycampaigns\events\CustomerEvent;
use yii\base\Event;
// Before sending invitation
Event::on(
CustomersService::class,
CustomersService::EVENT_BEFORE_SEND_INVITATION,
function(CustomerEvent $event) {
// Access: $event->customer, $event->campaign
// Set $event->isValid = false to cancel
}
);
// After sending invitation
Event::on(
CustomersService::class,
CustomersService::EVENT_AFTER_SEND_INVITATION,
function(CustomerEvent $event) {
// Access: $event->customer, $event->success
}
);- Check SMS Manager is configured: Ensure providers and sender IDs are set up
- Check Bitly API key: Required for SMS URL shortening
- Check queue is running:
./craft queue/run - Check logs: Survey Campaigns → System Logs
- Verify invitation code: Check the URL has a valid
invitationCodeparameter - Check customer exists: The invitation code must match a customer record
- Check campaign has form: The campaign must have a Formie form assigned
- Check CSV format: Must have
Namecolumn at minimum - Check encoding: Use UTF-8 encoding for special characters
- Check file size: Large files are processed in batches
- Verify API key: Check
BITLY_API_KEYenvironment variable - Check API limits: Bitly has rate limits on free plans
- Fallback: If Bitly fails, original URLs are used
Survey Campaigns uses the LindemannRock Logging Library for system logging.
- Error: Critical errors only (default)
- Warning: Errors and warnings
- Info: General information
- Debug: Detailed debugging (requires devMode)
- Location:
storage/logs/formie-campaigns-YYYY-MM-DD.log - Retention: 30 days (automatic cleanup)
- Web Interface: View logs at Survey Campaigns → System Logs
- Documentation: https://github.com/LindemannRock/craft-survey-campaigns
- Issues: https://github.com/LindemannRock/craft-survey-campaigns/issues
- Email: support@lindemannrock.com
This plugin is licensed under the MIT License. See LICENSE for details.
Developed by LindemannRock