The Campaign API handles the full lifecycle of advertising campaigns, including creation, status transitions, budget reservation, and pricing calculations. Campaigns support three pricing models — flat-rate, CPM (cost per mille), and CPC (cost per click) — each with its own budget handling logic.
Managing Campaigns
All campaign operations go through the Campaign_Manager singleton:
use WBAM_Pro\Modules\Campaigns\Campaign_Manager;
$manager = Campaign_Manager::get_instance();
// Create campaign
$campaign_id = $manager->create( array(
'advertiser_id' => $advertiser_id,
'name' => 'Summer Sale',
'budget' => 500.00,
'pricing_model' => 'cpm', // cpm, cpc, flat
'cpm_rate' => 2.50,
'start_date' => '2024-06-01',
'end_date' => '2024-08-31',
'status' => 'active',
) );
// Get campaign
$campaign = $manager->get( $campaign_id );
// Pause campaign
$manager->pause( $campaign_id, 'manual' );
// Resume campaign
$manager->resume( $campaign_id );
// Get campaign stats
$stats = $manager->get_stats( $campaign_id );
// Returns: impressions, clicks, ctr, spent, remaining_budget
Pricing Calculator
Use the Pricing_Calculator to estimate and compute campaign costs:
use WBAM_Pro\Modules\Campaigns\Pricing_Calculator;
$calculator = Pricing_Calculator::get_instance();
// Calculate CPM cost
$cost = $calculator->calculate_cpm( $impressions, $cpm_rate );
// Calculate CPC cost
$cost = $calculator->calculate_cpc( $clicks, $cpc_rate );
// Estimate campaign cost
$estimate = $calculator->estimate( array(
'pricing_model' => 'cpm',
'rate' => 2.50,
'impressions' => 100000,
'duration_days' => 30,
) );
Budget Reservation System
CPM and CPC campaigns with a budget greater than zero use a pre-funded reservation system. When a campaign is activated, the full budget amount is reserved (debited) from the advertiser’s wallet. When the campaign completes or is cancelled, any unspent budget is refunded.
How It Works
- Activation:
update_status('active')triggers the reservation. Thecreate()method alone does not reserve funds. - Pause: The reservation is held during pause. Resuming a paused campaign does not re-reserve funds.
- Completion/Cancellation: Unspent budget is automatically refunded to the advertiser’s wallet.
- Budget changes: Use
adjust_campaign_reservation()to handle budget modifications on active campaigns. - Flat-rate campaigns: Charged via
charge_for_package()— no reservation needed. - Unlimited budget (budget = 0): Billed hourly via
Billing_Manager.
Budget Calculation
- CPM:
price_per_unit * (impressions_limit / 1000) - CPC:
price_per_unit * clicks_limit - Flat: The package
pricefield is the total cost.
Status Transitions
Campaign status changes are enforced via Campaign::is_valid_transition(). The allowed transitions are:
| From | Allowed Transitions |
|---|---|
| draft | pending, active, cancelled |
| pending | active, cancelled |
| active | paused, completed, expired, cancelled |
| paused | active, completed, cancelled |
| completed | (terminal state — no transitions) |
| expired | (terminal state — no transitions) |
| cancelled | (terminal state — no transitions) |
Return Conventions
create()andupdate()returnCampaign|WP_Error.update_status(),delete(),activate(),pause(),complete(), andcancel()returntrue|WP_Error.- Always check results with
is_wp_error($result)sinceWP_Erroris truthy in PHP.
Code Example: Budget Alert Integration
add_action( 'wbam_pro_campaign_budget_exhausted', function( $campaign_id, $spent, $budget ) {
$campaign = wbam_pro_get_campaign( $campaign_id );
$advertiser = wbam_pro_get_advertiser( $campaign['advertiser_id'] );
// Send Slack notification
wp_remote_post( 'https://hooks.slack.com/services/xxx', array(
'body' => wp_json_encode( array(
'text' => sprintf(
'Campaign "%s" for %s has exhausted its budget ($%s)',
$campaign['name'],
$advertiser['company_name'],
number_format( $budget, 2 )
),
) ),
'headers' => array( 'Content-Type' => 'application/json' ),
) );
}, 10, 3 );
