Skip to content

Hooks and Filters Reference

MediaShield overviewFree + ProGet MediaShield →

Hooks Pro adds to its own surfaces use the mediashield_pro_* prefix. A few Pro-fired hooks predate that convention and still use the plain mediashield_* prefix (mediashield_lms_lesson_completed, mediashield_lms_adapters_loaded). They are fired as-is in 1.3.0 - there is no do_action_deprecated() shim in the code today. The two DRM packaging actions that used to be on this list were removed in 1.3.0.

Fired when Pro is fully initialized (end of Core\Plugin::__construct(), on plugins_loaded priority 20). No arguments.

add_action( 'mediashield_pro_loaded', function() {
// Pro is ready
} );

Fires before Pro’s GDPR eraser runs. Mutate $counters by reference to include your own removals.

add_action( 'mediashield_pro_privacy_before_erase', function( $email, $user, $page, $counters ) {
if ( $user ) {
$counters->items_removed += my_addon_delete( $user->ID );
}
}, 10, 4 );

$user is a WP_User or false for a guest email. $counters is a plain object with items_removed and items_retained int properties.

Fires after an LMS lesson is auto-completed from a video milestone. Arguments: ( int $user_id, int $video_id, int $lesson_id, string $lms_slug ).

Fires after adapters are registered. Read-only: an action cannot mutate the adapter array. Use the mediashield_lms_adapters filter to register an adapter.

These are queued jobs rather than extension points, but they are real hooks you can observe or enqueue.

Hook Enqueued by Arguments
mediashield_fire_webhook Milestones\AdvancedActions, async, on a webhook milestone action ( string $url, array $payload )
mediashield_generate_pdf REST\ExportController, async, on POST /export/pdf/report ( int $user_id, array $filters, string $report_id )
ms_vpn_lookup Analytics\VpnDetection, single action at session start ( string $ip, int $user_id, int $video_id )

All three run in the mediashield-pro Action Scheduler group. mediashield_fire_webhook falls back to a synchronous call when Action Scheduler is unavailable; the PDF route returns a 500 export_no_scheduler error instead.

Filter the final GDPR erase result array before it is returned to WordPress.

add_filter( 'mediashield_pro_privacy_erase_result', function( $result, $email, $user, $page ) {
$result['messages'][] = 'Synced with CRM.';
return $result;
}, 10, 4 );

Same shape for the exporter: ( array $result, string $email, WP_User|false $user, int $page ). $result carries data (WP exporter item array) and done (bool).

mediashield_pro_render_linked_lesson_video

Section titled “mediashield_pro_render_linked_lesson_video”

Control whether Pro auto-appends the linked video to an LMS lesson’s content. Return false to suppress when your theme handles rendering.

add_filter( 'mediashield_pro_render_linked_lesson_video', function( $render, $video_id, $post_id ) {
if ( 'my-theme' === get_template() ) {
return false;
}
return $render;
}, 10, 3 );

Override the license check result. Use in local development to bypass the outbound license check. (define( 'MEDIASHIELD_PRO_LICENSE_BYPASS', true ) in wp-config.php short-circuits the same check earlier.)

add_filter( 'mediashield_pro_license_valid', '__return_true' );

Register a custom LMS adapter. The filter passes a map of slug => adapter instance; entries must be objects implementing MediaShieldPro\LMS\LMSAdapterInterface. Class-name strings are rejected with a _doing_it_wrong() notice.

add_filter( 'mediashield_lms_adapters', function( $adapters ) {
$adapters['my_lms'] = new MyPlugin\LMS\MyLMSAdapter();
return $adapters;
} );

The filter runs on plugins_loaded priority 30, so register your callback before that.

mediashield_pro_playback_event_retention_days

Section titled “mediashield_pro_playback_event_retention_days”

Days of raw ms_playback_events rows to keep before the daily prune. Default 90, floored at 2.

add_filter( 'mediashield_pro_playback_event_retention_days', fn() => 30 );

The VPN/proxy lookup endpoint template. The bundled default is ip-api.com’s HTTPS endpoint, which requires the owner’s paid key. %1$s receives the URL-encoded IP and %2$s the key; a template using only %s receives the IP. Pointing this at your own resolver also removes the key requirement, because the check for “is detection usable” passes as soon as the endpoint differs from the bundled default.

Filter Value
mediashield_pro_bunny_stream_url ( string $url, string $platform_video_id, int $video_id ) - the derived Bunny playback URL
mediashield_pro_bunny_direct_play bool, default from ms_bunny_direct_play - serve a real <video> instead of Bunny’s iframe
mediashield_pro_bunny_prefer_mp4 bool, default from ms_bunny_prefer_mp4 - MP4 rendition instead of HLS
mediashield_pro_bunny_token_ttl int seconds, default 6 hours - CDN token lifetime
mediashield_pro_bunny_token_key string - the Bunny CDN token key used for signing
Free hook Pro subscriber Priority Purpose
mediashield_can_watch RoleAccess 20 Role restriction
mediashield_can_watch LMS adapters 25 Enrollment gates
mediashield_settings_response ProSettings, DRMSettings, AdvancedConfig 10 Inject Pro settings into GET /settings
mediashield_settings_update ProSettings, DRMSettings, AdvancedConfig 10 Save Pro settings on PUT /settings
mediashield_protection_levels Core\Plugin 10 Adds the experimental drm protection level, only while ms_drm_method is not none
mediashield_player_type Core\Plugin 10 Override to 'drm' when _ms_protection_level is drm and ms_drm_method is not none
mediashield_upload_drivers Core\Plugin 10 Register Bunny, Vimeo, YouTube, Wistia drivers
mediashield_watermark_config Watermark\AdvancedConfig 10 Extend with 7 configurable fields
mediashield_milestone_reached AdvancedActions 10 Fire webhook, email, or user-meta tag on milestone
mediashield_milestone_reached LMS adapters 10 Auto-complete linked lesson
mediashield_session_started SuspiciousActivity 10 Multi-IP detection
mediashield_session_started VpnDetection 20 Queue VPN/proxy lookup (only when enabled and keyed)
mediashield_devtools_detected SuspiciousActivity 10 Log devtools detection
the_content LMS\LMSManager 20 Append the linked video to an LMS lesson or topic
rest_request_after_callbacks Analytics\PlaybackRecorder 10 Record a playback event from each free session heartbeat

GDPR: Pro registers its own exporter and eraser with WordPress core (wp_privacy_personal_data_exporters / wp_privacy_personal_data_erasers). It does not subscribe to free’s mediashield_privacy_before_erase.