API
1 week ago
Abilities
1 week ago
Blocks
3 weeks ago
License
1 month ago
OAuth
1 week ago
AdminNotice.php
2 months ago
AdminNotices.php
2 months ago
AjaxActions.php
2 months ago
Blocks.php
2 years ago
Compatibility.php
11 months ago
FeatureAnnounce.php
1 week ago
Learn.php
1 week ago
Menu.php
1 week ago
Migrations.php
2 years ago
NpsSurvey.php
6 months ago
Onboarding.php
2 months ago
Player.php
3 weeks ago
PluginInstaller.php
1 week ago
PreloadService.php
2 years ago
ProCompatibility.php
3 weeks ago
ReusableVideos.php
2 months ago
RewriteRulesManager.php
2 years ago
Scripts.php
2 months ago
Settings.php
3 months ago
Shortcodes.php
1 week ago
Streamer.php
2 months ago
Translation.php
3 weeks ago
Usage.php
1 week ago
VideoPostType.php
3 weeks ago
Learn.php
825 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Learn tab progress tracking service. |
| 4 | * |
| 5 | * @package PrestoPlayer |
| 6 | * @subpackage Services |
| 7 | */ |
| 8 | |
| 9 | namespace PrestoPlayer\Services; |
| 10 | |
| 11 | /** |
| 12 | * Persists per-user progress on the Learn tab cards in user meta. |
| 13 | */ |
| 14 | class Learn { |
| 15 | |
| 16 | /** |
| 17 | * User meta key for storing learn progress. |
| 18 | * |
| 19 | * @var string |
| 20 | */ |
| 21 | const META_KEY = 'presto_player_learn_progress'; |
| 22 | |
| 23 | /** |
| 24 | * Register hooks. |
| 25 | */ |
| 26 | public function register() { |
| 27 | add_action( 'rest_api_init', array( $this, 'register_rest_routes' ) ); |
| 28 | } |
| 29 | |
| 30 | /** |
| 31 | * Register REST API routes. |
| 32 | */ |
| 33 | public function register_rest_routes() { |
| 34 | register_rest_route( |
| 35 | 'presto-player/v1', |
| 36 | '/get-learn-chapters', |
| 37 | array( |
| 38 | 'methods' => 'GET', |
| 39 | 'callback' => array( $this, 'get_learn_chapters' ), |
| 40 | 'permission_callback' => function () { |
| 41 | return current_user_can( 'publish_posts' ); |
| 42 | }, |
| 43 | ) |
| 44 | ); |
| 45 | |
| 46 | register_rest_route( |
| 47 | 'presto-player/v1', |
| 48 | '/update-learn-progress', |
| 49 | array( |
| 50 | 'methods' => 'POST', |
| 51 | 'callback' => array( $this, 'save_learn_progress' ), |
| 52 | 'permission_callback' => function () { |
| 53 | return current_user_can( 'publish_posts' ); |
| 54 | }, |
| 55 | 'args' => array( |
| 56 | 'chapterId' => array( |
| 57 | 'required' => true, |
| 58 | 'type' => 'string', |
| 59 | 'sanitize_callback' => 'sanitize_text_field', |
| 60 | ), |
| 61 | 'stepId' => array( |
| 62 | 'required' => true, |
| 63 | 'type' => 'string', |
| 64 | 'sanitize_callback' => 'sanitize_text_field', |
| 65 | ), |
| 66 | 'completed' => array( |
| 67 | 'required' => true, |
| 68 | 'type' => 'boolean', |
| 69 | ), |
| 70 | ), |
| 71 | ) |
| 72 | ); |
| 73 | } |
| 74 | |
| 75 | /** |
| 76 | * Get chapters with user progress merged. |
| 77 | * |
| 78 | * Returns the chapters array directly (not wrapped), |
| 79 | * matching the shape consumed by src/admin/dashboard/pages/learn/. |
| 80 | * |
| 81 | * @return \WP_REST_Response |
| 82 | */ |
| 83 | public function get_learn_chapters() { |
| 84 | $chapters = self::get_chapters_structure(); |
| 85 | $progress = get_user_meta( get_current_user_id(), self::META_KEY, true ); |
| 86 | |
| 87 | if ( ! is_array( $progress ) ) { |
| 88 | $progress = array(); |
| 89 | } |
| 90 | |
| 91 | // Merge progress into chapters. |
| 92 | foreach ( $chapters as &$chapter ) { |
| 93 | $chapter_id = $chapter['id']; |
| 94 | foreach ( $chapter['steps'] as &$step ) { |
| 95 | $step_id = $step['id']; |
| 96 | $step['completed'] = ! empty( $progress[ $chapter_id ][ $step_id ] ); |
| 97 | } |
| 98 | } |
| 99 | |
| 100 | return new \WP_REST_Response( $chapters, 200 ); |
| 101 | } |
| 102 | |
| 103 | /** |
| 104 | * Save progress for a single step. |
| 105 | * |
| 106 | * @param \WP_REST_Request $request Request object. |
| 107 | * @return \WP_REST_Response |
| 108 | */ |
| 109 | public function save_learn_progress( $request ) { |
| 110 | $chapter_id = $request->get_param( 'chapterId' ); |
| 111 | $step_id = $request->get_param( 'stepId' ); |
| 112 | $completed = (bool) $request->get_param( 'completed' ); |
| 113 | |
| 114 | $user_id = get_current_user_id(); |
| 115 | $progress = get_user_meta( $user_id, self::META_KEY, true ); |
| 116 | |
| 117 | if ( ! is_array( $progress ) ) { |
| 118 | $progress = array(); |
| 119 | } |
| 120 | |
| 121 | if ( ! isset( $progress[ $chapter_id ] ) ) { |
| 122 | $progress[ $chapter_id ] = array(); |
| 123 | } |
| 124 | |
| 125 | $progress[ $chapter_id ][ $step_id ] = $completed; |
| 126 | |
| 127 | update_user_meta( $user_id, self::META_KEY, $progress ); |
| 128 | |
| 129 | /** |
| 130 | * Fires after learn progress is saved for the current user. |
| 131 | * |
| 132 | * @param array $progress Full progress array for the user (all chapters/steps). |
| 133 | */ |
| 134 | do_action( 'presto_player_learn_progress_saved', $progress ); |
| 135 | |
| 136 | return new \WP_REST_Response( |
| 137 | array( |
| 138 | 'success' => true, |
| 139 | ), |
| 140 | 200 |
| 141 | ); |
| 142 | } |
| 143 | |
| 144 | /** |
| 145 | * Check if all steps in a chapter are completed for the given progress. |
| 146 | * |
| 147 | * @param array $chapter Single chapter array from get_chapters_structure(). |
| 148 | * @param array $progress Full progress array (chapter_id => step_id => bool). |
| 149 | * @return bool True if every step in the chapter is completed. |
| 150 | */ |
| 151 | public static function is_chapter_complete( $chapter, $progress ) { |
| 152 | $chapter_id = isset( $chapter['id'] ) ? $chapter['id'] : ''; |
| 153 | if ( empty( $chapter_id ) || empty( $chapter['steps'] ) || ! is_array( $chapter['steps'] ) ) { |
| 154 | return false; |
| 155 | } |
| 156 | |
| 157 | foreach ( $chapter['steps'] as $step ) { |
| 158 | $step_id = isset( $step['id'] ) ? $step['id'] : ''; |
| 159 | if ( empty( $step_id ) ) { |
| 160 | continue; |
| 161 | } |
| 162 | if ( empty( $progress[ $chapter_id ][ $step_id ] ) ) { |
| 163 | return false; |
| 164 | } |
| 165 | } |
| 166 | |
| 167 | return true; |
| 168 | } |
| 169 | |
| 170 | /** |
| 171 | * Get the chapters and steps structure. |
| 172 | * |
| 173 | * Shape (mirrors the SureDash Learn module so the admin dashboard |
| 174 | * components render uniformly across both plugins): |
| 175 | * - chapter.id string Kebab-case identifier. |
| 176 | * - chapter.title string Localized heading. |
| 177 | * - chapter.description string Localized subheading shown under the title. |
| 178 | * - chapter.docsUrl string Optional "Learn how" external link. |
| 179 | * - chapter.isNew bool Optional; shows a "New" badge on the card. |
| 180 | * - chapter.steps array Ordered list of step arrays. |
| 181 | * |
| 182 | * - step.id string Unique within the chapter. |
| 183 | * - step.title string Localized step title. |
| 184 | * - step.description string Localized body copy shown when expanded. |
| 185 | * - step.docsUrl string Optional "Read documentation" link. |
| 186 | * - step.headerAction array { label, url } — optional primary CTA. |
| 187 | * - step.isPro bool Whether the step is a Pro upsell. |
| 188 | * - step.screenshot array { url, alt } — optional screenshot image. |
| 189 | * - step.prompts array Optional list of example prompt strings. |
| 190 | * |
| 191 | * Optional string fields default to empty; the frontend hides the |
| 192 | * corresponding affordance when empty. `completed` is injected by |
| 193 | * get_learn_chapters() from user meta and is not part of this static tree. |
| 194 | * |
| 195 | * @return array |
| 196 | */ |
| 197 | public static function get_chapters_structure() { |
| 198 | $dashboard_base = 'admin.php?page=presto-dashboard&post_type=pp_video_block'; |
| 199 | |
| 200 | return array( |
| 201 | // Chapter 1 — Getting Started. |
| 202 | array( |
| 203 | 'id' => 'getting-started', |
| 204 | 'title' => __( 'Getting Started', 'presto-player' ), |
| 205 | 'description' => __( 'Create your first video and learn the core Presto Player workflow.', 'presto-player' ), |
| 206 | 'docsUrl' => '', |
| 207 | 'steps' => array( |
| 208 | array( |
| 209 | 'id' => 'add-first-video', |
| 210 | 'title' => __( 'Add a Presto Player video block', 'presto-player' ), |
| 211 | 'description' => __( 'Create a Presto Player video block in the block editor and embed your first video — from YouTube, Vimeo, or a self-hosted file.', 'presto-player' ), |
| 212 | 'docsUrl' => 'https://prestoplayer.com/docs/using-presto-player-with-gutenberg/', |
| 213 | 'headerAction' => array( |
| 214 | 'label' => __( 'Create Video', 'presto-player' ), |
| 215 | 'url' => admin_url( 'post-new.php?post_type=pp_video_block' ), |
| 216 | ), |
| 217 | 'isPro' => false, |
| 218 | 'screenshot' => array( |
| 219 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-New-Media-Presto.jpg', |
| 220 | 'alt' => __( 'Add a Presto Player video block', 'presto-player' ), |
| 221 | ), |
| 222 | ), |
| 223 | array( |
| 224 | 'id' => 'choose-video-source', |
| 225 | 'title' => __( 'Choose your video source', 'presto-player' ), |
| 226 | 'description' => __( 'Learn the difference between YouTube, Vimeo, self-hosted, and Bunny.net — pick the right source for your use case.', 'presto-player' ), |
| 227 | 'docsUrl' => 'https://prestoplayer.com/docs/presto-player-any-host/', |
| 228 | 'headerAction' => array( |
| 229 | 'label' => '', |
| 230 | 'url' => '', |
| 231 | ), |
| 232 | 'isPro' => false, |
| 233 | 'screenshot' => array( |
| 234 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Choose-Your-Media-Source-Presto.jpg', |
| 235 | 'alt' => __( 'Choose your video source', 'presto-player' ), |
| 236 | ), |
| 237 | ), |
| 238 | array( |
| 239 | 'id' => 'manage-media-hub', |
| 240 | 'title' => __( 'Manage your Media Hub', 'presto-player' ), |
| 241 | 'description' => __( 'Browse, search, and organize all your videos in one central library. The Media Hub is your video command center.', 'presto-player' ), |
| 242 | 'docsUrl' => 'https://prestoplayer.com/docs/video-sync/', |
| 243 | 'headerAction' => array( |
| 244 | 'label' => __( 'Open Media Hub', 'presto-player' ), |
| 245 | 'url' => admin_url( $dashboard_base . '&tab=MediaHub' ), |
| 246 | ), |
| 247 | 'isPro' => false, |
| 248 | 'screenshot' => array( |
| 249 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/05/Screenshot-2026-05-07-at-2.11.19-PM-1-scaled.png', |
| 250 | 'alt' => __( 'Manage your Media Hub', 'presto-player' ), |
| 251 | ), |
| 252 | ), |
| 253 | array( |
| 254 | 'id' => 'use-shortcodes', |
| 255 | 'title' => __( 'Use shortcodes to embed anywhere', 'presto-player' ), |
| 256 | 'description' => __( 'Copy a shortcode from the Media Hub to embed videos in widgets, classic editor, or any page builder that supports shortcodes.', 'presto-player' ), |
| 257 | 'docsUrl' => 'https://prestoplayer.com/docs/presto-shortcodes/', |
| 258 | 'headerAction' => array( |
| 259 | 'label' => __( 'View Media Hub', 'presto-player' ), |
| 260 | 'url' => admin_url( $dashboard_base . '&tab=MediaHub' ), |
| 261 | ), |
| 262 | 'isPro' => false, |
| 263 | 'screenshot' => array( |
| 264 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Screenshot-2026-04-28-at-11.15.02-PM.png', |
| 265 | 'alt' => __( 'Use shortcodes to embed anywhere', 'presto-player' ), |
| 266 | ), |
| 267 | ), |
| 268 | ), |
| 269 | ), |
| 270 | // Chapter 2 — Player Customization. |
| 271 | array( |
| 272 | 'id' => 'player-customization', |
| 273 | 'title' => __( 'Player Customization', 'presto-player' ), |
| 274 | 'description' => __( 'Fine-tune how your videos look, feel, and behave.', 'presto-player' ), |
| 275 | 'docsUrl' => '', |
| 276 | 'steps' => array( |
| 277 | array( |
| 278 | 'id' => 'customize-controls', |
| 279 | 'title' => __( 'Customize player controls', 'presto-player' ), |
| 280 | 'description' => __( 'Choose which controls are visible — play, progress, volume, speed, fullscreen, PiP, and more.', 'presto-player' ), |
| 281 | 'docsUrl' => 'https://prestoplayer.com/docs/how-to-use-video-presets/', |
| 282 | 'headerAction' => array( |
| 283 | 'label' => __( 'Edit Preset', 'presto-player' ), |
| 284 | 'url' => admin_url( $dashboard_base . '&tab=Settings§ion=presets' ), |
| 285 | ), |
| 286 | 'isPro' => false, |
| 287 | 'screenshot' => array( |
| 288 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Edit-Preset-Presto.jpg', |
| 289 | 'alt' => __( 'Customize player controls', 'presto-player' ), |
| 290 | ), |
| 291 | ), |
| 292 | array( |
| 293 | 'id' => 'configure-playback', |
| 294 | 'title' => __( 'Configure playback behavior', 'presto-player' ), |
| 295 | 'description' => __( 'Set autoplay, muted start, save position, play-in-viewport, and preload options per preset.', 'presto-player' ), |
| 296 | 'docsUrl' => 'https://prestoplayer.com/docs/play-inline-option-explained/', |
| 297 | 'headerAction' => array( |
| 298 | 'label' => __( 'Edit Preset', 'presto-player' ), |
| 299 | 'url' => admin_url( $dashboard_base . '&tab=Settings§ion=presets' ), |
| 300 | ), |
| 301 | 'isPro' => false, |
| 302 | 'screenshot' => array( |
| 303 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Configure-Playback-Behavior-Presto.jpg', |
| 304 | 'alt' => __( 'Configure playback behavior', 'presto-player' ), |
| 305 | ), |
| 306 | ), |
| 307 | array( |
| 308 | 'id' => 'add-captions', |
| 309 | 'title' => __( 'Add captions & subtitles', 'presto-player' ), |
| 310 | 'description' => __( 'Upload SRT/VTT caption files or enable auto-generated captions to make your videos accessible.', 'presto-player' ), |
| 311 | 'docsUrl' => 'https://prestoplayer.com/docs/how-to-create-video-captions/', |
| 312 | 'headerAction' => array( |
| 313 | 'label' => '', |
| 314 | 'url' => '', |
| 315 | ), |
| 316 | 'isPro' => false, |
| 317 | 'screenshot' => array( |
| 318 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Upload-Captions-for-Bunny-Presto.jpg', |
| 319 | 'alt' => __( 'Add captions and subtitles', 'presto-player' ), |
| 320 | ), |
| 321 | ), |
| 322 | array( |
| 323 | 'id' => 'add-timestamps', |
| 324 | 'title' => __( 'Add chapters to videos', 'presto-player' ), |
| 325 | 'description' => __( 'Create clickable chapter markers so viewers can jump to specific sections inside a video.', 'presto-player' ), |
| 326 | 'docsUrl' => 'https://prestoplayer.com/docs/presto-timestamps/', |
| 327 | 'headerAction' => array( |
| 328 | 'label' => '', |
| 329 | 'url' => '', |
| 330 | ), |
| 331 | 'isPro' => false, |
| 332 | 'screenshot' => array( |
| 333 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-Clickable-Chapters-Presto.jpg', |
| 334 | 'alt' => __( 'Add chapters to videos', 'presto-player' ), |
| 335 | ), |
| 336 | ), |
| 337 | array( |
| 338 | 'id' => 'setup-audio', |
| 339 | 'title' => __( 'Set up audio playback', 'presto-player' ), |
| 340 | 'description' => __( 'Use the dedicated audio block for podcasts, music, or voice content — same preset system as video.', 'presto-player' ), |
| 341 | 'docsUrl' => 'https://prestoplayer.com/docs/presto-player-audio/', |
| 342 | 'headerAction' => array( |
| 343 | 'label' => '', |
| 344 | 'url' => '', |
| 345 | ), |
| 346 | 'isPro' => false, |
| 347 | 'screenshot' => array( |
| 348 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Presto-Audio-Playback-Presto-Player.jpg', |
| 349 | 'alt' => __( 'Set up audio playback', 'presto-player' ), |
| 350 | ), |
| 351 | ), |
| 352 | array( |
| 353 | 'id' => 'add-custom-css', |
| 354 | 'title' => __( 'Add custom CSS to the player', 'presto-player' ), |
| 355 | 'description' => __( 'Inject custom CSS for advanced visual tweaks beyond the built-in branding options.', 'presto-player' ), |
| 356 | 'docsUrl' => 'https://prestoplayer.com/docs/how-to-customize-presets/', |
| 357 | 'headerAction' => array( |
| 358 | 'label' => __( 'Edit Custom CSS', 'presto-player' ), |
| 359 | 'url' => admin_url( $dashboard_base . '&tab=Settings§ion=custom-css' ), |
| 360 | ), |
| 361 | 'isPro' => true, |
| 362 | 'screenshot' => array( |
| 363 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Screenshot-2026-04-28-at-11.03.38-PM-scaled.png', |
| 364 | 'alt' => __( 'Add custom CSS to the player', 'presto-player' ), |
| 365 | ), |
| 366 | ), |
| 367 | ), |
| 368 | ), |
| 369 | // Chapter 3 — Branding & Presets. |
| 370 | array( |
| 371 | 'id' => 'branding-presets', |
| 372 | 'title' => __( 'Branding & Presets', 'presto-player' ), |
| 373 | 'description' => __( 'Match the player to your brand and save reusable configurations.', 'presto-player' ), |
| 374 | 'docsUrl' => '', |
| 375 | 'steps' => array( |
| 376 | array( |
| 377 | 'id' => 'set-brand-color', |
| 378 | 'title' => __( 'Set your brand color', 'presto-player' ), |
| 379 | 'description' => __( 'Choose a color for the play button, progress bar, and interactive elements to match your site identity.', 'presto-player' ), |
| 380 | 'docsUrl' => 'https://prestoplayer.com/docs/how-to-customize-presets/', |
| 381 | 'headerAction' => array( |
| 382 | 'label' => __( 'Set Color', 'presto-player' ), |
| 383 | 'url' => admin_url( $dashboard_base . '&tab=Settings§ion=branding' ), |
| 384 | ), |
| 385 | 'isPro' => false, |
| 386 | 'screenshot' => array( |
| 387 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Setup-Brand-Color-Presto.jpg', |
| 388 | 'alt' => __( 'Set your brand color', 'presto-player' ), |
| 389 | ), |
| 390 | ), |
| 391 | array( |
| 392 | 'id' => 'create-preset', |
| 393 | 'title' => __( 'Create a video preset', 'presto-player' ), |
| 394 | 'description' => __( 'Save a reusable preset with your preferred controls, autoplay, and style settings — apply it across multiple videos in one click.', 'presto-player' ), |
| 395 | 'docsUrl' => 'https://prestoplayer.com/docs/video-presets/', |
| 396 | 'headerAction' => array( |
| 397 | 'label' => __( 'Create Preset', 'presto-player' ), |
| 398 | 'url' => admin_url( $dashboard_base . '&tab=Settings§ion=presets' ), |
| 399 | ), |
| 400 | 'isPro' => false, |
| 401 | 'screenshot' => array( |
| 402 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Create-a-New-Preset-Presto.jpg', |
| 403 | 'alt' => __( 'Create a video preset', 'presto-player' ), |
| 404 | ), |
| 405 | ), |
| 406 | array( |
| 407 | 'id' => 'add-logo', |
| 408 | 'title' => __( 'Add a logo watermark', 'presto-player' ), |
| 409 | 'description' => __( 'Upload your logo to display as a clickable watermark on your videos — professional branding in one click.', 'presto-player' ), |
| 410 | 'docsUrl' => 'https://prestoplayer.com/docs/dynamic-watermark/', |
| 411 | 'headerAction' => array( |
| 412 | 'label' => __( 'Upload Logo', 'presto-player' ), |
| 413 | 'url' => admin_url( $dashboard_base . '&tab=Settings§ion=branding' ), |
| 414 | ), |
| 415 | 'isPro' => true, |
| 416 | 'screenshot' => array( |
| 417 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-Logo-Watermark-in-Preset-Presto.jpg', |
| 418 | 'alt' => __( 'Add a logo watermark', 'presto-player' ), |
| 419 | ), |
| 420 | ), |
| 421 | ), |
| 422 | ), |
| 423 | // Chapter 4 — Embedding & Page Builders. |
| 424 | array( |
| 425 | 'id' => 'embedding-page-builders', |
| 426 | 'title' => __( 'Embedding & Page Builders', 'presto-player' ), |
| 427 | 'description' => __( 'Place videos anywhere on your site — Gutenberg, Elementor, Divi, Beaver Builder, or shortcodes.', 'presto-player' ), |
| 428 | 'docsUrl' => '', |
| 429 | 'steps' => array( |
| 430 | array( |
| 431 | 'id' => 'embed-gutenberg', |
| 432 | 'title' => __( 'Add a video in Gutenberg', 'presto-player' ), |
| 433 | 'description' => __( 'Open the block editor, add a Presto Player block, select your video source, and publish.', 'presto-player' ), |
| 434 | 'docsUrl' => 'https://prestoplayer.com/docs/using-presto-player-with-gutenberg/', |
| 435 | 'headerAction' => array( |
| 436 | 'label' => __( 'Add to Page', 'presto-player' ), |
| 437 | 'url' => admin_url( 'post-new.php' ), |
| 438 | ), |
| 439 | 'isPro' => false, |
| 440 | 'screenshot' => array( |
| 441 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-Presto-Block-in-Gutenberg-Presto.jpg', |
| 442 | 'alt' => __( 'Add a video in Gutenberg', 'presto-player' ), |
| 443 | ), |
| 444 | ), |
| 445 | array( |
| 446 | 'id' => 'embed-elementor', |
| 447 | 'title' => __( 'Add a video in Elementor', 'presto-player' ), |
| 448 | 'description' => __( 'Use the Presto Player Elementor widget to embed videos in any Elementor layout or template.', 'presto-player' ), |
| 449 | 'docsUrl' => 'https://prestoplayer.com/docs/using-presto-player-with-elementor/', |
| 450 | 'headerAction' => array( |
| 451 | 'label' => '', |
| 452 | 'url' => '', |
| 453 | ), |
| 454 | 'isPro' => false, |
| 455 | 'screenshot' => array( |
| 456 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-Presto-Widget-using-Elementor-Presto.jpg', |
| 457 | 'alt' => __( 'Add a video in Elementor', 'presto-player' ), |
| 458 | ), |
| 459 | ), |
| 460 | array( |
| 461 | 'id' => 'embed-beaver-builder', |
| 462 | 'title' => __( 'Add a video in Beaver Builder', 'presto-player' ), |
| 463 | 'description' => __( 'Use the Presto Player module inside any Beaver Builder page or template.', 'presto-player' ), |
| 464 | 'docsUrl' => 'https://prestoplayer.com/docs/using-presto-player-with-beaver-builder/', |
| 465 | 'headerAction' => array( |
| 466 | 'label' => '', |
| 467 | 'url' => '', |
| 468 | ), |
| 469 | 'isPro' => false, |
| 470 | 'screenshot' => array( |
| 471 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-Presto-module-in-Beaver-Builder.jpg', |
| 472 | 'alt' => __( 'Add a video in Beaver Builder', 'presto-player' ), |
| 473 | ), |
| 474 | ), |
| 475 | array( |
| 476 | 'id' => 'embed-classic-editor', |
| 477 | 'title' => __( 'Use with the Classic Editor', 'presto-player' ), |
| 478 | 'description' => __( 'Embed videos via shortcodes in the classic WordPress editor — paste the shortcode and publish.', 'presto-player' ), |
| 479 | 'docsUrl' => 'https://prestoplayer.com/docs/use-with-classic-editor/', |
| 480 | 'headerAction' => array( |
| 481 | 'label' => '', |
| 482 | 'url' => '', |
| 483 | ), |
| 484 | 'isPro' => false, |
| 485 | 'screenshot' => array( |
| 486 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/ce-classic-editor-shortcode-scaled.png', |
| 487 | 'alt' => __( 'Use with the Classic Editor', 'presto-player' ), |
| 488 | ), |
| 489 | ), |
| 490 | array( |
| 491 | 'id' => 'create-popup', |
| 492 | 'title' => __( 'Create a video popup', 'presto-player' ), |
| 493 | 'description' => __( 'Launch videos in a lightbox popup triggered by a button, image, or link — grab attention without leaving the page.', 'presto-player' ), |
| 494 | 'docsUrl' => 'https://prestoplayer.com/docs/presto-popups/', |
| 495 | 'headerAction' => array( |
| 496 | 'label' => __( 'Try Popups', 'presto-player' ), |
| 497 | 'url' => admin_url( 'post-new.php?post_type=page' ), |
| 498 | ), |
| 499 | 'isPro' => true, |
| 500 | 'screenshot' => array( |
| 501 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-Presto-Popups-Presto-Player.jpg', |
| 502 | 'alt' => __( 'Create a video popup', 'presto-player' ), |
| 503 | ), |
| 504 | ), |
| 505 | array( |
| 506 | 'id' => 'create-playlist', |
| 507 | 'title' => __( 'Create a playlist', 'presto-player' ), |
| 508 | 'description' => __( 'Group related videos into a sequential playlist — perfect for course modules, series, or curated content collections.', 'presto-player' ), |
| 509 | 'docsUrl' => 'https://prestoplayer.com/docs/presto-player-playlists/', |
| 510 | 'headerAction' => array( |
| 511 | 'label' => __( 'Create Playlist', 'presto-player' ), |
| 512 | 'url' => admin_url( 'post-new.php?post_type=page' ), |
| 513 | ), |
| 514 | 'isPro' => true, |
| 515 | 'screenshot' => array( |
| 516 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Presto-Playlist-Block-Presto-.jpg', |
| 517 | 'alt' => __( 'Create a playlist', 'presto-player' ), |
| 518 | ), |
| 519 | ), |
| 520 | ), |
| 521 | ), |
| 522 | // Chapter 5 — Analytics & Engagement. |
| 523 | array( |
| 524 | 'id' => 'analytics-engagement', |
| 525 | 'title' => __( 'Analytics & Engagement', 'presto-player' ), |
| 526 | 'description' => __( 'Track how your audience watches and turn viewers into leads.', 'presto-player' ), |
| 527 | 'docsUrl' => '', |
| 528 | 'steps' => array( |
| 529 | array( |
| 530 | 'id' => 'enable-analytics', |
| 531 | 'title' => __( 'Enable analytics', 'presto-player' ), |
| 532 | 'description' => __( 'Turn on view tracking to collect watch data — views, watch time, and engagement — for every video on your site.', 'presto-player' ), |
| 533 | 'docsUrl' => '', |
| 534 | 'headerAction' => array( |
| 535 | 'label' => __( 'Enable Analytics', 'presto-player' ), |
| 536 | 'url' => admin_url( $dashboard_base . '&tab=Settings§ion=viewing-analytics' ), |
| 537 | ), |
| 538 | 'isPro' => true, |
| 539 | 'screenshot' => array( |
| 540 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Enable-Analytics-Presto.jpg', |
| 541 | 'alt' => __( 'Enable analytics', 'presto-player' ), |
| 542 | ), |
| 543 | ), |
| 544 | array( |
| 545 | 'id' => 'view-insights', |
| 546 | 'title' => __( 'View video insights', 'presto-player' ), |
| 547 | 'description' => __( 'See total views, average watch time, and engagement trends per video from the Analytics dashboard.', 'presto-player' ), |
| 548 | 'docsUrl' => '', |
| 549 | 'headerAction' => array( |
| 550 | 'label' => __( 'View Analytics', 'presto-player' ), |
| 551 | 'url' => admin_url( $dashboard_base . '&tab=Analytics' ), |
| 552 | ), |
| 553 | 'isPro' => true, |
| 554 | 'screenshot' => array( |
| 555 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/View-Analytics-Presto.jpg', |
| 556 | 'alt' => __( 'View video insights', 'presto-player' ), |
| 557 | ), |
| 558 | ), |
| 559 | array( |
| 560 | 'id' => 'track-user-engagement', |
| 561 | 'title' => __( 'Track per-user engagement', 'presto-player' ), |
| 562 | 'description' => __( 'See exactly who watched what and for how long — powerful for course creators and membership sites.', 'presto-player' ), |
| 563 | 'docsUrl' => '', |
| 564 | 'headerAction' => array( |
| 565 | 'label' => __( 'View Analytics', 'presto-player' ), |
| 566 | 'url' => admin_url( $dashboard_base . '&tab=Analytics' ), |
| 567 | ), |
| 568 | 'isPro' => true, |
| 569 | 'screenshot' => array( |
| 570 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Track-Per-User-Engagement-Presto.jpg', |
| 571 | 'alt' => __( 'Track per-user engagement', 'presto-player' ), |
| 572 | ), |
| 573 | ), |
| 574 | array( |
| 575 | 'id' => 'setup-email-capture', |
| 576 | 'title' => __( 'Set up email capture', 'presto-player' ), |
| 577 | 'description' => __( 'Capture email addresses mid-video and sync subscribers with your email marketing tool automatically.', 'presto-player' ), |
| 578 | 'docsUrl' => 'https://prestoplayer.com/docs/how-to-capture-emails/', |
| 579 | 'headerAction' => array( |
| 580 | 'label' => __( 'Configure Email', 'presto-player' ), |
| 581 | 'url' => admin_url( $dashboard_base . '&tab=Settings§ion=email-capture' ), |
| 582 | ), |
| 583 | 'isPro' => true, |
| 584 | 'screenshot' => array( |
| 585 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Email-Capture-Presto.jpg', |
| 586 | 'alt' => __( 'Set up email capture', 'presto-player' ), |
| 587 | ), |
| 588 | ), |
| 589 | array( |
| 590 | 'id' => 'connect-google-analytics', |
| 591 | 'title' => __( 'Connect Google Analytics', 'presto-player' ), |
| 592 | 'description' => __( 'Send video play events to your existing GA4 property for unified site-wide analytics tracking.', 'presto-player' ), |
| 593 | 'docsUrl' => '', |
| 594 | 'headerAction' => array( |
| 595 | 'label' => __( 'Configure GA', 'presto-player' ), |
| 596 | 'url' => admin_url( $dashboard_base . '&tab=Settings§ion=google-analytics' ), |
| 597 | ), |
| 598 | 'isPro' => true, |
| 599 | 'screenshot' => array( |
| 600 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Connect-Presto-with-Existing-GA-Presto.jpg', |
| 601 | 'alt' => __( 'Connect Google Analytics', 'presto-player' ), |
| 602 | ), |
| 603 | ), |
| 604 | ), |
| 605 | ), |
| 606 | // Chapter 6 — Integrations & Advanced. |
| 607 | array( |
| 608 | 'id' => 'integrations-advanced', |
| 609 | 'title' => __( 'Integrations & Advanced', 'presto-player' ), |
| 610 | 'description' => __( 'Connect Presto Player with your LMS, CDN, CRM, and SEO tools.', 'presto-player' ), |
| 611 | 'docsUrl' => '', |
| 612 | 'steps' => array( |
| 613 | array( |
| 614 | 'id' => 'connect-bunny', |
| 615 | 'title' => __( 'Connect Bunny.net for private hosting', 'presto-player' ), |
| 616 | 'description' => __( 'Set up Bunny.net Stream for CDN-powered private video hosting with adaptive HLS streaming — fast, secure, global.', 'presto-player' ), |
| 617 | 'docsUrl' => 'https://prestoplayer.com/docs/bunnycdn/', |
| 618 | 'headerAction' => array( |
| 619 | 'label' => __( 'Connect Bunny', 'presto-player' ), |
| 620 | 'url' => admin_url( $dashboard_base . '&tab=Settings§ion=bunny-net' ), |
| 621 | ), |
| 622 | 'isPro' => true, |
| 623 | 'screenshot' => array( |
| 624 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/PP-BNS-01.png', |
| 625 | 'alt' => __( 'Connect Bunny.net for private hosting', 'presto-player' ), |
| 626 | ), |
| 627 | ), |
| 628 | array( |
| 629 | 'id' => 'use-bunny-library', |
| 630 | 'title' => __( 'Use the Bunny.net video library', 'presto-player' ), |
| 631 | 'description' => __( 'Browse and embed videos directly from your Bunny.net library without leaving WordPress.', 'presto-player' ), |
| 632 | 'docsUrl' => 'https://prestoplayer.com/docs/bunnynet-video-library-integration/', |
| 633 | 'headerAction' => array( |
| 634 | 'label' => '', |
| 635 | 'url' => '', |
| 636 | ), |
| 637 | 'isPro' => true, |
| 638 | 'screenshot' => array( |
| 639 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Connect-BunnyNet-Videos-Presto.jpg', |
| 640 | 'alt' => __( 'Use the Bunny.net video library', 'presto-player' ), |
| 641 | ), |
| 642 | ), |
| 643 | array( |
| 644 | 'id' => 'auto-captions-bunny', |
| 645 | 'title' => __( 'Enable automatic captions', 'presto-player' ), |
| 646 | 'description' => __( 'Let Bunny.net auto-transcribe your videos and generate caption files — hands-free accessibility.', 'presto-player' ), |
| 647 | 'docsUrl' => 'https://prestoplayer.com/docs/automatic-captions/', |
| 648 | 'headerAction' => array( |
| 649 | 'label' => '', |
| 650 | 'url' => '', |
| 651 | ), |
| 652 | 'isPro' => true, |
| 653 | 'screenshot' => array( |
| 654 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Enable-Automatic-Captions-Presto.jpg', |
| 655 | 'alt' => __( 'Enable automatic captions', 'presto-player' ), |
| 656 | ), |
| 657 | ), |
| 658 | array( |
| 659 | 'id' => 'integrate-learndash', |
| 660 | 'title' => __( 'Integrate with LearnDash', 'presto-player' ), |
| 661 | 'description' => __( 'Track video progress as course completion — students must watch to advance to the next lesson.', 'presto-player' ), |
| 662 | 'docsUrl' => 'https://prestoplayer.com/docs/use-presto-player-with-learndash/', |
| 663 | 'headerAction' => array( |
| 664 | 'label' => '', |
| 665 | 'url' => '', |
| 666 | ), |
| 667 | 'isPro' => true, |
| 668 | 'screenshot' => array( |
| 669 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2021/12/pp-1-7-video-progresion-learndash.png', |
| 670 | 'alt' => __( 'Integrate with LearnDash', 'presto-player' ), |
| 671 | ), |
| 672 | ), |
| 673 | array( |
| 674 | 'id' => 'integrate-lifterlms', |
| 675 | 'title' => __( 'Integrate with LifterLMS', 'presto-player' ), |
| 676 | 'description' => __( 'Connect Presto Player with LifterLMS for video-based course progression and completion tracking.', 'presto-player' ), |
| 677 | 'docsUrl' => 'https://prestoplayer.com/docs/lifterlms-advanced-videos-presto-player/', |
| 678 | 'headerAction' => array( |
| 679 | 'label' => '', |
| 680 | 'url' => '', |
| 681 | ), |
| 682 | 'isPro' => true, |
| 683 | 'screenshot' => array( |
| 684 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2021/11/pp-lifter-settings-courses.png', |
| 685 | 'alt' => __( 'Integrate with LifterLMS', 'presto-player' ), |
| 686 | ), |
| 687 | ), |
| 688 | array( |
| 689 | 'id' => 'integrate-tutorlms', |
| 690 | 'title' => __( 'Integrate with TutorLMS', 'presto-player' ), |
| 691 | 'description' => __( 'Use Presto Player as the video engine for TutorLMS courses — full progress tracking included.', 'presto-player' ), |
| 692 | 'docsUrl' => 'https://prestoplayer.com/docs/tutorlms/', |
| 693 | 'headerAction' => array( |
| 694 | 'label' => '', |
| 695 | 'url' => '', |
| 696 | ), |
| 697 | 'isPro' => true, |
| 698 | 'screenshot' => array( |
| 699 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2024/06/video-source.png', |
| 700 | 'alt' => __( 'Integrate with TutorLMS', 'presto-player' ), |
| 701 | ), |
| 702 | ), |
| 703 | array( |
| 704 | 'id' => 'connect-fluent-crm', |
| 705 | 'title' => __( 'Connect Fluent CRM', 'presto-player' ), |
| 706 | 'description' => __( 'Sync email captures and video engagement data with Fluent CRM for automated marketing workflows.', 'presto-player' ), |
| 707 | 'docsUrl' => 'https://prestoplayer.com/docs/fluent-crm-presto-player/', |
| 708 | 'headerAction' => array( |
| 709 | 'label' => '', |
| 710 | 'url' => '', |
| 711 | ), |
| 712 | 'isPro' => true, |
| 713 | 'screenshot' => array( |
| 714 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2021/10/image-3-2-1024x900.png', |
| 715 | 'alt' => __( 'Connect Fluent CRM', 'presto-player' ), |
| 716 | ), |
| 717 | ), |
| 718 | array( |
| 719 | 'id' => 'optimize-video-seo', |
| 720 | 'title' => __( 'Optimize video SEO with RankMath', 'presto-player' ), |
| 721 | 'description' => __( 'Add structured video schema data to boost search visibility — works automatically with RankMath.', 'presto-player' ), |
| 722 | 'docsUrl' => 'https://prestoplayer.com/docs/seo-optimize-presto-player-videos-using-rank-math/', |
| 723 | 'headerAction' => array( |
| 724 | 'label' => '', |
| 725 | 'url' => '', |
| 726 | ), |
| 727 | 'isPro' => false, |
| 728 | 'screenshot' => array( |
| 729 | 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/PP-SEO-01.png', |
| 730 | 'alt' => __( 'Optimize video SEO with RankMath', 'presto-player' ), |
| 731 | ), |
| 732 | ), |
| 733 | ), |
| 734 | ), |
| 735 | // Chapter 7 — AI Abilities. |
| 736 | array( |
| 737 | 'id' => 'presto-player-ai', |
| 738 | 'title' => __( 'AI Abilities', 'presto-player' ), |
| 739 | 'description' => __( 'Let Claude, ChatGPT or Cursor manage your videos. Just ask, in plain English.', 'presto-player' ), |
| 740 | 'docsUrl' => '', |
| 741 | 'isNew' => true, |
| 742 | 'steps' => array( |
| 743 | array( |
| 744 | 'id' => 'enable-ai-access', |
| 745 | 'title' => __( 'Turn on AI access', 'presto-player' ), |
| 746 | 'description' => __( 'Switch on AI access in the settings so assistants like Claude, ChatGPT and Cursor can securely connect to your site.', 'presto-player' ), |
| 747 | 'docsUrl' => '', |
| 748 | 'headerAction' => array( |
| 749 | 'label' => __( 'Open AI Settings', 'presto-player' ), |
| 750 | 'url' => admin_url( $dashboard_base . '&tab=Settings§ion=mcp' ), |
| 751 | ), |
| 752 | 'isPro' => false, |
| 753 | 'screenshot' => array( |
| 754 | 'url' => '', |
| 755 | 'alt' => '', |
| 756 | ), |
| 757 | ), |
| 758 | array( |
| 759 | 'id' => 'allow-changes', |
| 760 | 'title' => __( 'Allow AI to make changes', 'presto-player' ), |
| 761 | 'description' => __( 'By default AI is read-only — it can list, search and report on your videos and analytics, but cannot change anything. Turn on “Allow AI to make changes” to let it create, update and delete too. Enable this only when you trust the assistant, because it can then modify or permanently remove content on your site.', 'presto-player' ), |
| 762 | 'docsUrl' => '', |
| 763 | 'headerAction' => array( |
| 764 | 'label' => '', |
| 765 | 'url' => '', |
| 766 | ), |
| 767 | 'isPro' => false, |
| 768 | 'screenshot' => array( |
| 769 | 'url' => '', |
| 770 | 'alt' => '', |
| 771 | ), |
| 772 | ), |
| 773 | array( |
| 774 | 'id' => 'what-you-can-ask', |
| 775 | 'title' => __( 'What you can ask', 'presto-player' ), |
| 776 | 'description' => __( 'Just talk to it in plain English. Here are some things you can say:', 'presto-player' ), |
| 777 | 'docsUrl' => '', |
| 778 | 'headerAction' => array( |
| 779 | 'label' => '', |
| 780 | 'url' => '', |
| 781 | ), |
| 782 | 'prompts' => array( |
| 783 | __( 'Add this YouTube video and give me the shortcode', 'presto-player' ), |
| 784 | __( 'Embed this Vimeo video on my site', 'presto-player' ), |
| 785 | __( 'Upload my MP4 as a self-hosted player', 'presto-player' ), |
| 786 | __( 'Which videos got the most views this month?', 'presto-player' ), |
| 787 | __( 'Where do viewers drop off in this video?', 'presto-player' ), |
| 788 | __( 'Who are my most active viewers?', 'presto-player' ), |
| 789 | __( 'Show me all videos with ‘training’ in the title', 'presto-player' ), |
| 790 | __( 'Rename this video and update its description', 'presto-player' ), |
| 791 | __( 'Get the shortcode for this video', 'presto-player' ), |
| 792 | __( 'Auto-generate chapters from the captions on this video', 'presto-player' ), |
| 793 | __( 'Translate this video’s captions to Spanish', 'presto-player' ), |
| 794 | ), |
| 795 | 'isPro' => false, |
| 796 | 'screenshot' => array( |
| 797 | 'url' => '', |
| 798 | 'alt' => '', |
| 799 | ), |
| 800 | ), |
| 801 | array( |
| 802 | 'id' => 'search-library', |
| 803 | 'title' => __( 'Search your library', 'presto-player' ), |
| 804 | 'description' => __( 'Not sure what is possible? Open the AI settings — every ability is listed there with a search box, so you can see exactly what the assistant can do. And in chat, just ask it to find things and it searches your Media Hub and analytics for you.', 'presto-player' ), |
| 805 | 'docsUrl' => '', |
| 806 | 'headerAction' => array( |
| 807 | 'label' => __( 'Open AI Settings', 'presto-player' ), |
| 808 | 'url' => admin_url( $dashboard_base . '&tab=Settings§ion=mcp' ), |
| 809 | ), |
| 810 | 'prompts' => array( |
| 811 | __( 'Show me all my videos about ‘onboarding’', 'presto-player' ), |
| 812 | __( 'Find the video I embedded on my pricing page', 'presto-player' ), |
| 813 | ), |
| 814 | 'isPro' => false, |
| 815 | 'screenshot' => array( |
| 816 | 'url' => '', |
| 817 | 'alt' => '', |
| 818 | ), |
| 819 | ), |
| 820 | ), |
| 821 | ), |
| 822 | ); |
| 823 | } |
| 824 | } |
| 825 |