PluginProbe ʕ •ᴥ•ʔ
Presto Player / 4.3.1
Presto Player v4.3.1
4.3.1 4.3.0 4.2.4 4.2.3 4.2.2 4.2.0 4.2.1 trunk 1.10.0 1.10.1 1.10.2 1.11.0 1.12.0 1.13.0 1.14.0 1.14.1 1.5.10 1.5.11 1.5.12 1.5.13 1.5.14 1.5.15 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.10 1.6.11 1.6.12 1.6.13 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.8.0 1.8.1 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.11 2.0.12 2.0.13 2.0.14 2.0.15 2.0.16 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.2.0 2.2.1 2.2.2 2.2.3 2.2.3-beta1 2.3.0 2.3.1 2.3.2 2.3.3 3.0.0 3.0.0-beta1 3.0.1 3.0.2 3.0.3 3.0.4 3.0.5 3.0.6 3.0.7 3.0.8 3.1.0 3.1.1 3.1.2 3.1.3 4.0.0 4.0.1 4.0.2 4.0.3 4.0.4 4.0.5 4.0.6 4.0.7 4.0.8 4.1.0 4.1.1 4.1.2 4.1.3 4.1.4
presto-player / inc / Services / Learn.php
presto-player / inc / Services Last commit date
API 1 month ago Blocks 10 months ago License 1 month ago AdminNotice.php 3 weeks ago AdminNotices.php 3 weeks ago AjaxActions.php 3 weeks ago Blocks.php 1 year ago Compatibility.php 10 months ago Learn.php 1 month ago Menu.php 1 month ago Migrations.php 1 year ago NpsSurvey.php 5 months ago Onboarding.php 3 weeks ago Player.php 3 days ago PluginInstaller.php 1 month ago PreloadService.php 1 year ago ProCompatibility.php 1 month ago ReusableVideos.php 2 weeks ago RewriteRulesManager.php 1 year ago Scripts.php 2 weeks ago Settings.php 1 month ago Shortcodes.php 1 month ago Streamer.php 3 weeks ago Translation.php 3 weeks ago Usage.php 3 weeks ago VideoPostType.php 2 weeks ago
Learn.php
736 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.steps array Ordered list of step arrays.
180 *
181 * - step.id string Unique within the chapter.
182 * - step.title string Localized step title.
183 * - step.description string Localized body copy shown when expanded.
184 * - step.docsUrl string Optional "Read documentation" link.
185 * - step.headerAction array { label, url } — optional primary CTA.
186 * - step.isPro bool Whether the step is a Pro upsell.
187 * - step.screenshot array { url, alt } — optional screenshot image.
188 *
189 * Optional string fields default to empty; the frontend hides the
190 * corresponding affordance when empty. `completed` is injected by
191 * get_learn_chapters() from user meta and is not part of this static tree.
192 *
193 * @return array
194 */
195 public static function get_chapters_structure() {
196 $dashboard_base = 'admin.php?page=presto-dashboard&post_type=pp_video_block';
197
198 return array(
199 // Chapter 1 — Getting Started.
200 array(
201 'id' => 'getting-started',
202 'title' => __( 'Getting Started', 'presto-player' ),
203 'description' => __( 'Create your first video and learn the core Presto Player workflow.', 'presto-player' ),
204 'docsUrl' => '',
205 'steps' => array(
206 array(
207 'id' => 'add-first-video',
208 'title' => __( 'Add a Presto Player video block', 'presto-player' ),
209 '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' ),
210 'docsUrl' => 'https://prestoplayer.com/docs/using-presto-player-with-gutenberg/',
211 'headerAction' => array(
212 'label' => __( 'Create Video', 'presto-player' ),
213 'url' => admin_url( 'post-new.php?post_type=pp_video_block' ),
214 ),
215 'isPro' => false,
216 'screenshot' => array(
217 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-New-Media-Presto.jpg',
218 'alt' => __( 'Add a Presto Player video block', 'presto-player' ),
219 ),
220 ),
221 array(
222 'id' => 'choose-video-source',
223 'title' => __( 'Choose your video source', 'presto-player' ),
224 'description' => __( 'Learn the difference between YouTube, Vimeo, self-hosted, and Bunny.net — pick the right source for your use case.', 'presto-player' ),
225 'docsUrl' => 'https://prestoplayer.com/docs/presto-player-any-host/',
226 'headerAction' => array(
227 'label' => '',
228 'url' => '',
229 ),
230 'isPro' => false,
231 'screenshot' => array(
232 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Choose-Your-Media-Source-Presto.jpg',
233 'alt' => __( 'Choose your video source', 'presto-player' ),
234 ),
235 ),
236 array(
237 'id' => 'manage-media-hub',
238 'title' => __( 'Manage your Media Hub', 'presto-player' ),
239 'description' => __( 'Browse, search, and organize all your videos in one central library. The Media Hub is your video command center.', 'presto-player' ),
240 'docsUrl' => 'https://prestoplayer.com/docs/video-sync/',
241 'headerAction' => array(
242 'label' => __( 'Open Media Hub', 'presto-player' ),
243 'url' => admin_url( $dashboard_base . '&tab=MediaHub' ),
244 ),
245 'isPro' => false,
246 'screenshot' => array(
247 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/05/Screenshot-2026-05-07-at-2.11.19-PM-1-scaled.png',
248 'alt' => __( 'Manage your Media Hub', 'presto-player' ),
249 ),
250 ),
251 array(
252 'id' => 'use-shortcodes',
253 'title' => __( 'Use shortcodes to embed anywhere', 'presto-player' ),
254 'description' => __( 'Copy a shortcode from the Media Hub to embed videos in widgets, classic editor, or any page builder that supports shortcodes.', 'presto-player' ),
255 'docsUrl' => 'https://prestoplayer.com/docs/presto-shortcodes/',
256 'headerAction' => array(
257 'label' => __( 'View Media Hub', 'presto-player' ),
258 'url' => admin_url( $dashboard_base . '&tab=MediaHub' ),
259 ),
260 'isPro' => false,
261 'screenshot' => array(
262 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Screenshot-2026-04-28-at-11.15.02-PM.png',
263 'alt' => __( 'Use shortcodes to embed anywhere', 'presto-player' ),
264 ),
265 ),
266 ),
267 ),
268 // Chapter 2 — Player Customization.
269 array(
270 'id' => 'player-customization',
271 'title' => __( 'Player Customization', 'presto-player' ),
272 'description' => __( 'Fine-tune how your videos look, feel, and behave.', 'presto-player' ),
273 'docsUrl' => '',
274 'steps' => array(
275 array(
276 'id' => 'customize-controls',
277 'title' => __( 'Customize player controls', 'presto-player' ),
278 'description' => __( 'Choose which controls are visible — play, progress, volume, speed, fullscreen, PiP, and more.', 'presto-player' ),
279 'docsUrl' => 'https://prestoplayer.com/docs/how-to-use-video-presets/',
280 'headerAction' => array(
281 'label' => __( 'Edit Preset', 'presto-player' ),
282 'url' => admin_url( $dashboard_base . '&tab=Settings&section=presets' ),
283 ),
284 'isPro' => false,
285 'screenshot' => array(
286 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Edit-Preset-Presto.jpg',
287 'alt' => __( 'Customize player controls', 'presto-player' ),
288 ),
289 ),
290 array(
291 'id' => 'configure-playback',
292 'title' => __( 'Configure playback behavior', 'presto-player' ),
293 'description' => __( 'Set autoplay, muted start, save position, play-in-viewport, and preload options per preset.', 'presto-player' ),
294 'docsUrl' => 'https://prestoplayer.com/docs/play-inline-option-explained/',
295 'headerAction' => array(
296 'label' => __( 'Edit Preset', 'presto-player' ),
297 'url' => admin_url( $dashboard_base . '&tab=Settings&section=presets' ),
298 ),
299 'isPro' => false,
300 'screenshot' => array(
301 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Configure-Playback-Behavior-Presto.jpg',
302 'alt' => __( 'Configure playback behavior', 'presto-player' ),
303 ),
304 ),
305 array(
306 'id' => 'add-captions',
307 'title' => __( 'Add captions & subtitles', 'presto-player' ),
308 'description' => __( 'Upload SRT/VTT caption files or enable auto-generated captions to make your videos accessible.', 'presto-player' ),
309 'docsUrl' => 'https://prestoplayer.com/docs/how-to-create-video-captions/',
310 'headerAction' => array(
311 'label' => '',
312 'url' => '',
313 ),
314 'isPro' => false,
315 'screenshot' => array(
316 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Upload-Captions-for-Bunny-Presto.jpg',
317 'alt' => __( 'Add captions and subtitles', 'presto-player' ),
318 ),
319 ),
320 array(
321 'id' => 'add-timestamps',
322 'title' => __( 'Add chapters to videos', 'presto-player' ),
323 'description' => __( 'Create clickable chapter markers so viewers can jump to specific sections inside a video.', 'presto-player' ),
324 'docsUrl' => 'https://prestoplayer.com/docs/presto-timestamps/',
325 'headerAction' => array(
326 'label' => '',
327 'url' => '',
328 ),
329 'isPro' => false,
330 'screenshot' => array(
331 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-Clickable-Chapters-Presto.jpg',
332 'alt' => __( 'Add chapters to videos', 'presto-player' ),
333 ),
334 ),
335 array(
336 'id' => 'setup-audio',
337 'title' => __( 'Set up audio playback', 'presto-player' ),
338 'description' => __( 'Use the dedicated audio block for podcasts, music, or voice content — same preset system as video.', 'presto-player' ),
339 'docsUrl' => 'https://prestoplayer.com/docs/presto-player-audio/',
340 'headerAction' => array(
341 'label' => '',
342 'url' => '',
343 ),
344 'isPro' => false,
345 'screenshot' => array(
346 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Presto-Audio-Playback-Presto-Player.jpg',
347 'alt' => __( 'Set up audio playback', 'presto-player' ),
348 ),
349 ),
350 array(
351 'id' => 'add-custom-css',
352 'title' => __( 'Add custom CSS to the player', 'presto-player' ),
353 'description' => __( 'Inject custom CSS for advanced visual tweaks beyond the built-in branding options.', 'presto-player' ),
354 'docsUrl' => 'https://prestoplayer.com/docs/how-to-customize-presets/',
355 'headerAction' => array(
356 'label' => __( 'Edit Custom CSS', 'presto-player' ),
357 'url' => admin_url( $dashboard_base . '&tab=Settings&section=custom-css' ),
358 ),
359 'isPro' => true,
360 'screenshot' => array(
361 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Screenshot-2026-04-28-at-11.03.38-PM-scaled.png',
362 'alt' => __( 'Add custom CSS to the player', 'presto-player' ),
363 ),
364 ),
365 ),
366 ),
367 // Chapter 3 — Branding & Presets.
368 array(
369 'id' => 'branding-presets',
370 'title' => __( 'Branding & Presets', 'presto-player' ),
371 'description' => __( 'Match the player to your brand and save reusable configurations.', 'presto-player' ),
372 'docsUrl' => '',
373 'steps' => array(
374 array(
375 'id' => 'set-brand-color',
376 'title' => __( 'Set your brand color', 'presto-player' ),
377 'description' => __( 'Choose a color for the play button, progress bar, and interactive elements to match your site identity.', 'presto-player' ),
378 'docsUrl' => 'https://prestoplayer.com/docs/how-to-customize-presets/',
379 'headerAction' => array(
380 'label' => __( 'Set Color', 'presto-player' ),
381 'url' => admin_url( $dashboard_base . '&tab=Settings&section=branding' ),
382 ),
383 'isPro' => false,
384 'screenshot' => array(
385 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Setup-Brand-Color-Presto.jpg',
386 'alt' => __( 'Set your brand color', 'presto-player' ),
387 ),
388 ),
389 array(
390 'id' => 'create-preset',
391 'title' => __( 'Create a video preset', 'presto-player' ),
392 'description' => __( 'Save a reusable preset with your preferred controls, autoplay, and style settings — apply it across multiple videos in one click.', 'presto-player' ),
393 'docsUrl' => 'https://prestoplayer.com/docs/video-presets/',
394 'headerAction' => array(
395 'label' => __( 'Create Preset', 'presto-player' ),
396 'url' => admin_url( $dashboard_base . '&tab=Settings&section=presets' ),
397 ),
398 'isPro' => false,
399 'screenshot' => array(
400 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Create-a-New-Preset-Presto.jpg',
401 'alt' => __( 'Create a video preset', 'presto-player' ),
402 ),
403 ),
404 array(
405 'id' => 'add-logo',
406 'title' => __( 'Add a logo watermark', 'presto-player' ),
407 'description' => __( 'Upload your logo to display as a clickable watermark on your videos — professional branding in one click.', 'presto-player' ),
408 'docsUrl' => 'https://prestoplayer.com/docs/dynamic-watermark/',
409 'headerAction' => array(
410 'label' => __( 'Upload Logo', 'presto-player' ),
411 'url' => admin_url( $dashboard_base . '&tab=Settings&section=branding' ),
412 ),
413 'isPro' => true,
414 'screenshot' => array(
415 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-Logo-Watermark-in-Preset-Presto.jpg',
416 'alt' => __( 'Add a logo watermark', 'presto-player' ),
417 ),
418 ),
419 ),
420 ),
421 // Chapter 4 — Embedding & Page Builders.
422 array(
423 'id' => 'embedding-page-builders',
424 'title' => __( 'Embedding & Page Builders', 'presto-player' ),
425 'description' => __( 'Place videos anywhere on your site — Gutenberg, Elementor, Divi, Beaver Builder, or shortcodes.', 'presto-player' ),
426 'docsUrl' => '',
427 'steps' => array(
428 array(
429 'id' => 'embed-gutenberg',
430 'title' => __( 'Add a video in Gutenberg', 'presto-player' ),
431 'description' => __( 'Open the block editor, add a Presto Player block, select your video source, and publish.', 'presto-player' ),
432 'docsUrl' => 'https://prestoplayer.com/docs/using-presto-player-with-gutenberg/',
433 'headerAction' => array(
434 'label' => __( 'Add to Page', 'presto-player' ),
435 'url' => admin_url( 'post-new.php' ),
436 ),
437 'isPro' => false,
438 'screenshot' => array(
439 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-Presto-Block-in-Gutenberg-Presto.jpg',
440 'alt' => __( 'Add a video in Gutenberg', 'presto-player' ),
441 ),
442 ),
443 array(
444 'id' => 'embed-elementor',
445 'title' => __( 'Add a video in Elementor', 'presto-player' ),
446 'description' => __( 'Use the Presto Player Elementor widget to embed videos in any Elementor layout or template.', 'presto-player' ),
447 'docsUrl' => 'https://prestoplayer.com/docs/using-presto-player-with-elementor/',
448 'headerAction' => array(
449 'label' => '',
450 'url' => '',
451 ),
452 'isPro' => false,
453 'screenshot' => array(
454 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-Presto-Widget-using-Elementor-Presto.jpg',
455 'alt' => __( 'Add a video in Elementor', 'presto-player' ),
456 ),
457 ),
458 array(
459 'id' => 'embed-beaver-builder',
460 'title' => __( 'Add a video in Beaver Builder', 'presto-player' ),
461 'description' => __( 'Use the Presto Player module inside any Beaver Builder page or template.', 'presto-player' ),
462 'docsUrl' => 'https://prestoplayer.com/docs/using-presto-player-with-beaver-builder/',
463 'headerAction' => array(
464 'label' => '',
465 'url' => '',
466 ),
467 'isPro' => false,
468 'screenshot' => array(
469 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-Presto-module-in-Beaver-Builder.jpg',
470 'alt' => __( 'Add a video in Beaver Builder', 'presto-player' ),
471 ),
472 ),
473 array(
474 'id' => 'embed-classic-editor',
475 'title' => __( 'Use with the Classic Editor', 'presto-player' ),
476 'description' => __( 'Embed videos via shortcodes in the classic WordPress editor — paste the shortcode and publish.', 'presto-player' ),
477 'docsUrl' => 'https://prestoplayer.com/docs/use-with-classic-editor/',
478 'headerAction' => array(
479 'label' => '',
480 'url' => '',
481 ),
482 'isPro' => false,
483 'screenshot' => array(
484 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/ce-classic-editor-shortcode-scaled.png',
485 'alt' => __( 'Use with the Classic Editor', 'presto-player' ),
486 ),
487 ),
488 array(
489 'id' => 'create-popup',
490 'title' => __( 'Create a video popup', 'presto-player' ),
491 'description' => __( 'Launch videos in a lightbox popup triggered by a button, image, or link — grab attention without leaving the page.', 'presto-player' ),
492 'docsUrl' => 'https://prestoplayer.com/docs/presto-popups/',
493 'headerAction' => array(
494 'label' => __( 'Try Popups', 'presto-player' ),
495 'url' => admin_url( 'post-new.php?post_type=page' ),
496 ),
497 'isPro' => true,
498 'screenshot' => array(
499 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Add-Presto-Popups-Presto-Player.jpg',
500 'alt' => __( 'Create a video popup', 'presto-player' ),
501 ),
502 ),
503 array(
504 'id' => 'create-playlist',
505 'title' => __( 'Create a playlist', 'presto-player' ),
506 'description' => __( 'Group related videos into a sequential playlist — perfect for course modules, series, or curated content collections.', 'presto-player' ),
507 'docsUrl' => 'https://prestoplayer.com/docs/presto-player-playlists/',
508 'headerAction' => array(
509 'label' => __( 'Create Playlist', 'presto-player' ),
510 'url' => admin_url( 'post-new.php?post_type=page' ),
511 ),
512 'isPro' => true,
513 'screenshot' => array(
514 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Presto-Playlist-Block-Presto-.jpg',
515 'alt' => __( 'Create a playlist', 'presto-player' ),
516 ),
517 ),
518 ),
519 ),
520 // Chapter 5 — Analytics & Engagement.
521 array(
522 'id' => 'analytics-engagement',
523 'title' => __( 'Analytics & Engagement', 'presto-player' ),
524 'description' => __( 'Track how your audience watches and turn viewers into leads.', 'presto-player' ),
525 'docsUrl' => '',
526 'steps' => array(
527 array(
528 'id' => 'enable-analytics',
529 'title' => __( 'Enable analytics', 'presto-player' ),
530 'description' => __( 'Turn on view tracking to collect watch data — views, watch time, and engagement — for every video on your site.', 'presto-player' ),
531 'docsUrl' => '',
532 'headerAction' => array(
533 'label' => __( 'Enable Analytics', 'presto-player' ),
534 'url' => admin_url( $dashboard_base . '&tab=Settings&section=viewing-analytics' ),
535 ),
536 'isPro' => true,
537 'screenshot' => array(
538 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Enable-Analytics-Presto.jpg',
539 'alt' => __( 'Enable analytics', 'presto-player' ),
540 ),
541 ),
542 array(
543 'id' => 'view-insights',
544 'title' => __( 'View video insights', 'presto-player' ),
545 'description' => __( 'See total views, average watch time, and engagement trends per video from the Analytics dashboard.', 'presto-player' ),
546 'docsUrl' => '',
547 'headerAction' => array(
548 'label' => __( 'View Analytics', 'presto-player' ),
549 'url' => admin_url( $dashboard_base . '&tab=Analytics' ),
550 ),
551 'isPro' => true,
552 'screenshot' => array(
553 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/View-Analytics-Presto.jpg',
554 'alt' => __( 'View video insights', 'presto-player' ),
555 ),
556 ),
557 array(
558 'id' => 'track-user-engagement',
559 'title' => __( 'Track per-user engagement', 'presto-player' ),
560 'description' => __( 'See exactly who watched what and for how long — powerful for course creators and membership sites.', 'presto-player' ),
561 'docsUrl' => '',
562 'headerAction' => array(
563 'label' => __( 'View Analytics', 'presto-player' ),
564 'url' => admin_url( $dashboard_base . '&tab=Analytics' ),
565 ),
566 'isPro' => true,
567 'screenshot' => array(
568 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Track-Per-User-Engagement-Presto.jpg',
569 'alt' => __( 'Track per-user engagement', 'presto-player' ),
570 ),
571 ),
572 array(
573 'id' => 'setup-email-capture',
574 'title' => __( 'Set up email capture', 'presto-player' ),
575 'description' => __( 'Capture email addresses mid-video and sync subscribers with your email marketing tool automatically.', 'presto-player' ),
576 'docsUrl' => 'https://prestoplayer.com/docs/how-to-capture-emails/',
577 'headerAction' => array(
578 'label' => __( 'Configure Email', 'presto-player' ),
579 'url' => admin_url( $dashboard_base . '&tab=Settings&section=email-capture' ),
580 ),
581 'isPro' => true,
582 'screenshot' => array(
583 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Email-Capture-Presto.jpg',
584 'alt' => __( 'Set up email capture', 'presto-player' ),
585 ),
586 ),
587 array(
588 'id' => 'connect-google-analytics',
589 'title' => __( 'Connect Google Analytics', 'presto-player' ),
590 'description' => __( 'Send video play events to your existing GA4 property for unified site-wide analytics tracking.', 'presto-player' ),
591 'docsUrl' => '',
592 'headerAction' => array(
593 'label' => __( 'Configure GA', 'presto-player' ),
594 'url' => admin_url( $dashboard_base . '&tab=Settings&section=google-analytics' ),
595 ),
596 'isPro' => true,
597 'screenshot' => array(
598 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Connect-Presto-with-Existing-GA-Presto.jpg',
599 'alt' => __( 'Connect Google Analytics', 'presto-player' ),
600 ),
601 ),
602 ),
603 ),
604 // Chapter 6 — Integrations & Advanced.
605 array(
606 'id' => 'integrations-advanced',
607 'title' => __( 'Integrations & Advanced', 'presto-player' ),
608 'description' => __( 'Connect Presto Player with your LMS, CDN, CRM, and SEO tools.', 'presto-player' ),
609 'docsUrl' => '',
610 'steps' => array(
611 array(
612 'id' => 'connect-bunny',
613 'title' => __( 'Connect Bunny.net for private hosting', 'presto-player' ),
614 'description' => __( 'Set up Bunny.net Stream for CDN-powered private video hosting with adaptive HLS streaming — fast, secure, global.', 'presto-player' ),
615 'docsUrl' => 'https://prestoplayer.com/docs/bunnycdn/',
616 'headerAction' => array(
617 'label' => __( 'Connect Bunny', 'presto-player' ),
618 'url' => admin_url( $dashboard_base . '&tab=Settings&section=bunny-net' ),
619 ),
620 'isPro' => true,
621 'screenshot' => array(
622 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/PP-BNS-01.png',
623 'alt' => __( 'Connect Bunny.net for private hosting', 'presto-player' ),
624 ),
625 ),
626 array(
627 'id' => 'use-bunny-library',
628 'title' => __( 'Use the Bunny.net video library', 'presto-player' ),
629 'description' => __( 'Browse and embed videos directly from your Bunny.net library without leaving WordPress.', 'presto-player' ),
630 'docsUrl' => 'https://prestoplayer.com/docs/bunnynet-video-library-integration/',
631 'headerAction' => array(
632 'label' => '',
633 'url' => '',
634 ),
635 'isPro' => true,
636 'screenshot' => array(
637 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Connect-BunnyNet-Videos-Presto.jpg',
638 'alt' => __( 'Use the Bunny.net video library', 'presto-player' ),
639 ),
640 ),
641 array(
642 'id' => 'auto-captions-bunny',
643 'title' => __( 'Enable automatic captions', 'presto-player' ),
644 'description' => __( 'Let Bunny.net auto-transcribe your videos and generate caption files — hands-free accessibility.', 'presto-player' ),
645 'docsUrl' => 'https://prestoplayer.com/docs/automatic-captions/',
646 'headerAction' => array(
647 'label' => '',
648 'url' => '',
649 ),
650 'isPro' => true,
651 'screenshot' => array(
652 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/Enable-Automatic-Captions-Presto.jpg',
653 'alt' => __( 'Enable automatic captions', 'presto-player' ),
654 ),
655 ),
656 array(
657 'id' => 'integrate-learndash',
658 'title' => __( 'Integrate with LearnDash', 'presto-player' ),
659 'description' => __( 'Track video progress as course completion — students must watch to advance to the next lesson.', 'presto-player' ),
660 'docsUrl' => 'https://prestoplayer.com/docs/use-presto-player-with-learndash/',
661 'headerAction' => array(
662 'label' => '',
663 'url' => '',
664 ),
665 'isPro' => true,
666 'screenshot' => array(
667 'url' => 'https://prestoplayer.com/wp-content/uploads/2021/12/pp-1-7-video-progresion-learndash.png',
668 'alt' => __( 'Integrate with LearnDash', 'presto-player' ),
669 ),
670 ),
671 array(
672 'id' => 'integrate-lifterlms',
673 'title' => __( 'Integrate with LifterLMS', 'presto-player' ),
674 'description' => __( 'Connect Presto Player with LifterLMS for video-based course progression and completion tracking.', 'presto-player' ),
675 'docsUrl' => 'https://prestoplayer.com/docs/lifterlms-advanced-videos-presto-player/',
676 'headerAction' => array(
677 'label' => '',
678 'url' => '',
679 ),
680 'isPro' => true,
681 'screenshot' => array(
682 'url' => 'https://prestoplayer.com/wp-content/uploads/2021/11/pp-lifter-settings-courses.png',
683 'alt' => __( 'Integrate with LifterLMS', 'presto-player' ),
684 ),
685 ),
686 array(
687 'id' => 'integrate-tutorlms',
688 'title' => __( 'Integrate with TutorLMS', 'presto-player' ),
689 'description' => __( 'Use Presto Player as the video engine for TutorLMS courses — full progress tracking included.', 'presto-player' ),
690 'docsUrl' => 'https://prestoplayer.com/docs/tutorlms/',
691 'headerAction' => array(
692 'label' => '',
693 'url' => '',
694 ),
695 'isPro' => true,
696 'screenshot' => array(
697 'url' => 'https://prestoplayer.com/wp-content/uploads/2024/06/video-source.png',
698 'alt' => __( 'Integrate with TutorLMS', 'presto-player' ),
699 ),
700 ),
701 array(
702 'id' => 'connect-fluent-crm',
703 'title' => __( 'Connect Fluent CRM', 'presto-player' ),
704 'description' => __( 'Sync email captures and video engagement data with Fluent CRM for automated marketing workflows.', 'presto-player' ),
705 'docsUrl' => 'https://prestoplayer.com/docs/fluent-crm-presto-player/',
706 'headerAction' => array(
707 'label' => '',
708 'url' => '',
709 ),
710 'isPro' => true,
711 'screenshot' => array(
712 'url' => 'https://prestoplayer.com/wp-content/uploads/2021/10/image-3-2-1024x900.png',
713 'alt' => __( 'Connect Fluent CRM', 'presto-player' ),
714 ),
715 ),
716 array(
717 'id' => 'optimize-video-seo',
718 'title' => __( 'Optimize video SEO with RankMath', 'presto-player' ),
719 'description' => __( 'Add structured video schema data to boost search visibility — works automatically with RankMath.', 'presto-player' ),
720 'docsUrl' => 'https://prestoplayer.com/docs/seo-optimize-presto-player-videos-using-rank-math/',
721 'headerAction' => array(
722 'label' => '',
723 'url' => '',
724 ),
725 'isPro' => false,
726 'screenshot' => array(
727 'url' => 'https://prestoplayer.com/wp-content/uploads/2026/04/PP-SEO-01.png',
728 'alt' => __( 'Optimize video SEO with RankMath', 'presto-player' ),
729 ),
730 ),
731 ),
732 ),
733 );
734 }
735 }
736