Changeset 3447384
- Timestamp:
- 01/26/2026 09:25:31 PM (2 months ago)
- Location:
- bandwidth-saver
- Files:
-
- 20 edited
- 1 copied
-
tags/1.1 (copied) (copied from bandwidth-saver/trunk)
-
tags/1.1/admin/js/imgpro-cdn-admin.js (modified) (1 diff)
-
tags/1.1/imgpro-cdn.php (modified) (3 diffs)
-
tags/1.1/includes/class-imgpro-cdn-admin-ajax.php (modified) (8 diffs)
-
tags/1.1/includes/class-imgpro-cdn-admin.php (modified) (8 diffs)
-
tags/1.1/includes/class-imgpro-cdn-api.php (modified) (6 diffs)
-
tags/1.1/includes/class-imgpro-cdn-onboarding.php (modified) (12 diffs)
-
tags/1.1/includes/class-imgpro-cdn-plan-selector.php (modified) (4 diffs)
-
tags/1.1/includes/class-imgpro-cdn-rewriter.php (modified) (13 diffs)
-
tags/1.1/includes/class-imgpro-cdn-settings.php (modified) (9 diffs)
-
tags/1.1/readme.txt (modified) (10 diffs)
-
trunk/admin/js/imgpro-cdn-admin.js (modified) (1 diff)
-
trunk/imgpro-cdn.php (modified) (3 diffs)
-
trunk/includes/class-imgpro-cdn-admin-ajax.php (modified) (8 diffs)
-
trunk/includes/class-imgpro-cdn-admin.php (modified) (8 diffs)
-
trunk/includes/class-imgpro-cdn-api.php (modified) (6 diffs)
-
trunk/includes/class-imgpro-cdn-onboarding.php (modified) (12 diffs)
-
trunk/includes/class-imgpro-cdn-plan-selector.php (modified) (4 diffs)
-
trunk/includes/class-imgpro-cdn-rewriter.php (modified) (13 diffs)
-
trunk/includes/class-imgpro-cdn-settings.php (modified) (9 diffs)
-
trunk/readme.txt (modified) (10 diffs)
Legend:
- Unmodified
- Added
- Removed
-
bandwidth-saver/tags/1.1/admin/js/imgpro-cdn-admin.js
r3446766 r3447384 446 446 447 447 const originalText = $button.text(); 448 // Get tier from parameter, button data attribute, or default to ' unlimited'449 const tier = tierId || $button.data('tier') || ' unlimited';448 // Get tier from parameter, button data attribute, or default to 'image' 449 const tier = tierId || $button.data('tier') || 'image'; 450 450 $button.addClass('is-loading').prop('disabled', true).text(imgproCdnAdmin.i18n.creatingCheckout); 451 451 -
bandwidth-saver/tags/1.1/imgpro-cdn.php
r3446766 r3447384 1 1 <?php 2 2 /** 3 * Plugin Name: Bandwidth Saver: Unlimited MediaCDN3 * Plugin Name: Bandwidth Saver: Image CDN 4 4 * Plugin URI: https://github.com/img-pro/bandwidth-saver 5 * Description: Unlimited media CDN for images, video, audio, and HLS streaming. $19.99/mo for unlimited bandwidth.6 * Version: 1. 05 * Description: Image CDN for WordPress. Serve images from 300+ global edge servers. Faster Core Web Vitals, better SEO. $9.99/mo. 6 * Version: 1.1 7 7 * Author: ImgPro 8 8 * Author URI: https://img.pro … … 47 47 // Define plugin constants 48 48 if (!defined('IMGPRO_CDN_VERSION')) { 49 define('IMGPRO_CDN_VERSION', '1. 0');49 define('IMGPRO_CDN_VERSION', '1.1'); 50 50 } 51 51 if (!defined('IMGPRO_CDN_PLUGIN_DIR')) { … … 90 90 function imgpro_cdn_add_version_html() { 91 91 if (!is_admin()) { 92 echo "\n<!-- MediaCDN by ImgPro v" . esc_attr(IMGPRO_CDN_VERSION) . " -->\n";92 echo "\n<!-- Image CDN by ImgPro v" . esc_attr(IMGPRO_CDN_VERSION) . " -->\n"; 93 93 } 94 94 } -
bandwidth-saver/tags/1.1/includes/class-imgpro-cdn-admin-ajax.php
r3446766 r3447384 293 293 if ($current_enabled === $enabled) { 294 294 $message = $enabled 295 ? __(' Media CDN is active. Media isloading from Cloudflare.', 'bandwidth-saver')296 : __(' Media CDN is disabled. Media isloading from your server.', 'bandwidth-saver');295 ? __('Image CDN is active. Images are loading from Cloudflare.', 'bandwidth-saver') 296 : __('Image CDN is disabled. Images are loading from your server.', 'bandwidth-saver'); 297 297 298 298 wp_send_json_success(['message' => $message]); … … 313 313 if (false !== $result) { 314 314 $message = $enabled 315 ? __(' Media CDN enabled. Media now loadsfrom the global network.', 'bandwidth-saver')316 : __(' Media CDN disabled. Media now loadsfrom your server.', 'bandwidth-saver');315 ? __('Image CDN enabled. Images now load from the global network.', 'bandwidth-saver') 316 : __('Image CDN disabled. Images now load from your server.', 'bandwidth-saver'); 317 317 318 318 $response = ['message' => $message]; … … 600 600 ImgPro_CDN_Security::check_rate_limit('checkout'); 601 601 602 // Always upgrade to unlimited tier (single paid tier model)602 // Always upgrade to image tier (single paid tier model for Image CDN) 603 603 // tier_id parameter kept for backwards compatibility but ignored 604 $tier_id = ' unlimited';604 $tier_id = 'image'; 605 605 606 606 // SECURITY: Use get_api_key() to decrypt the stored API key … … 779 779 // Enable CDN if valid subscription 780 780 $current_tier_id = $this->api->get_tier_id($site); 781 if (in_array($current_tier_id, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_ UNLIMITED, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE], true)) {781 if (in_array($current_tier_id, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_IMAGE, ImgPro_CDN_Settings::TIER_UNLIMITED, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE], true)) { 782 782 $this->settings->update([ 783 783 'cloud_enabled' => true, … … 797 797 ImgPro_CDN_Settings::TIER_PRO => 3, 798 798 ImgPro_CDN_Settings::TIER_BUSINESS => 4, 799 ImgPro_CDN_Settings::TIER_IMAGE => 5, 799 800 ImgPro_CDN_Settings::TIER_UNLIMITED => 5, 800 801 ]; … … 1056 1057 1057 1058 wp_send_json_success([ 1058 'message' => __('CDN domain removed. The MediaCDN has been disabled.', 'bandwidth-saver')1059 'message' => __('CDN domain removed. The Image CDN has been disabled.', 'bandwidth-saver') 1059 1060 ]); 1060 1061 } … … 1117 1118 $tier_valid = in_array($tier, [ 1118 1119 ImgPro_CDN_Settings::TIER_FREE, 1120 ImgPro_CDN_Settings::TIER_IMAGE, 1119 1121 ImgPro_CDN_Settings::TIER_UNLIMITED, 1120 1122 ImgPro_CDN_Settings::TIER_LITE, … … 1418 1420 'count' => $full_response['count'] ?? count($source_urls), 1419 1421 'max_domains' => -1, // Unlimited for all users 1420 'tier_name' => $full_response['tier_name'] ?? ' Media CDN'1422 'tier_name' => $full_response['tier_name'] ?? 'Unlimited' 1421 1423 ]); 1422 1424 } -
bandwidth-saver/tags/1.1/includes/class-imgpro-cdn-admin.php
r3446766 r3447384 159 159 // Enable if subscription is valid 160 160 $tier_id = $this->api->get_tier_id($site); 161 $valid_tiers = [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_ UNLIMITED, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE];161 $valid_tiers = [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_IMAGE, ImgPro_CDN_Settings::TIER_UNLIMITED, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE]; 162 162 163 163 if (in_array($tier_id, $valid_tiers, true)) { … … 468 468 // Toggle UI text 469 469 'cdnActiveHeading' => __('Your media is loading faster', 'bandwidth-saver'), 470 'cdnInactiveHeading' => __(' MediaCDN is Off', 'bandwidth-saver'),470 'cdnInactiveHeading' => __('Image CDN is Off', 'bandwidth-saver'), 471 471 'cdnActiveDesc' => __('Visitors worldwide are getting faster page loads.', 'bandwidth-saver'), 472 472 'cdnInactiveDesc' => __('Turn on to speed up your media.', 'bandwidth-saver'), … … 479 479 'domainActive' => __('Custom domain is active.', 'bandwidth-saver'), 480 480 'confirmRemoveDomain' => __('Remove this custom domain? Media will be served from the default domain.', 'bandwidth-saver'), 481 'confirmRemoveCdnDomain' => __('Remove this CDN domain? The MediaCDN will be disabled.', 'bandwidth-saver'),481 'confirmRemoveCdnDomain' => __('Remove this CDN domain? The Image CDN will be disabled.', 'bandwidth-saver'), 482 482 'cdnDomainRemoved' => __('CDN domain removed.', 'bandwidth-saver'), 483 483 // Upgrade prompts … … 821 821 <h2 id="imgpro-toggle-heading"> 822 822 <?php echo $is_enabled 823 ? esc_html__('Your media isloading faster', 'bandwidth-saver')824 : esc_html__(' MediaCDN is Off', 'bandwidth-saver'); ?>823 ? esc_html__('Your images are loading faster', 'bandwidth-saver') 824 : esc_html__('Image CDN is Off', 'bandwidth-saver'); ?> 825 825 </h2> 826 826 <p id="imgpro-toggle-description"> 827 827 <?php echo $is_enabled 828 828 ? esc_html__('Visitors worldwide are getting faster page loads.', 'bandwidth-saver') 829 : esc_html__('Turn on to speed up your media.', 'bandwidth-saver'); ?>829 : esc_html__('Turn on to speed up your images.', 'bandwidth-saver'); ?> 830 830 </p> 831 831 </div> … … 843 843 > 844 844 <span class="imgpro-toggle-slider"></span> 845 <span class="screen-reader-text"><?php esc_html_e('Toggle MediaCDN', 'bandwidth-saver'); ?></span>845 <span class="screen-reader-text"><?php esc_html_e('Toggle Image CDN', 'bandwidth-saver'); ?></span> 846 846 </label> 847 847 </div> … … 1163 1163 private function render_cloud_tab($settings) { 1164 1164 $tier = $settings['cloud_tier'] ?? ImgPro_CDN_Settings::TIER_NONE; 1165 $has_subscription = in_array($tier, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_ UNLIMITED, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE, ImgPro_CDN_Settings::TIER_PAST_DUE], true);1165 $has_subscription = in_array($tier, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_IMAGE, ImgPro_CDN_Settings::TIER_UNLIMITED, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE, ImgPro_CDN_Settings::TIER_PAST_DUE], true); 1166 1166 ?> 1167 1167 <div class="imgpro-tab-panel" role="tabpanel"> … … 1285 1285 <span class="imgpro-account-card__status-text"><?php esc_html_e('Subscription Active', 'bandwidth-saver'); ?></span> 1286 1286 </div> 1287 <span class="imgpro-account-card__description"><?php esc_html_e('Unlimited mediadelivery from 300+ edge servers.', 'bandwidth-saver'); ?></span>1287 <span class="imgpro-account-card__description"><?php esc_html_e('Unlimited image delivery from 300+ edge servers.', 'bandwidth-saver'); ?></span> 1288 1288 <?php else: ?> 1289 <strong class="imgpro-account-card__headline"><?php esc_html_e('Enjoying the MediaCDN?', 'bandwidth-saver'); ?></strong>1289 <strong class="imgpro-account-card__headline"><?php esc_html_e('Enjoying the Image CDN?', 'bandwidth-saver'); ?></strong> 1290 1290 <span class="imgpro-account-card__description"><?php esc_html_e('Activate your subscription to support continued development.', 'bandwidth-saver'); ?></span> 1291 1291 <?php endif; ?> … … 1310 1310 <?php if ($is_paid && !empty($email)): ?> 1311 1311 <span class="imgpro-separator">·</span> 1312 <span class="imgpro-account-card__price"><?php esc_html_e('$ 19.99/mo', 'bandwidth-saver'); ?></span>1312 <span class="imgpro-account-card__price"><?php esc_html_e('$9.99/mo', 'bandwidth-saver'); ?></span> 1313 1313 <?php elseif (!$is_paid): ?> 1314 1314 <?php if (!empty($email)): ?> 1315 1315 <span class="imgpro-separator">·</span> 1316 1316 <?php endif; ?> 1317 <span class="imgpro-account-card__price"><?php esc_html_e('$ 19.99/mo', 'bandwidth-saver'); ?></span>1317 <span class="imgpro-account-card__price"><?php esc_html_e('$9.99/mo', 'bandwidth-saver'); ?></span> 1318 1318 <?php endif; ?> 1319 1319 </div> -
bandwidth-saver/tags/1.1/includes/class-imgpro-cdn-api.php
r3446766 r3447384 26 26 * @var string 27 27 */ 28 const BASE_URL = 'https:// cloud.wp.img.pro';28 const BASE_URL = 'https://billing.bandwidth-saver.com'; 29 29 30 30 /** … … 336 336 * 337 337 * @param string $api_key Site API key. 338 * @param string $tier_id Target tier ID (default: ' unlimited').338 * @param string $tier_id Target tier ID (default: 'image'). 339 339 * @return array|WP_Error Checkout data with URL or error. 340 340 */ 341 public function create_checkout($api_key, $tier_id = ' unlimited') {341 public function create_checkout($api_key, $tier_id = 'image') { 342 342 if (empty($api_key)) { 343 343 return new WP_Error('missing_api_key', __('API key is required', 'bandwidth-saver')); … … 838 838 [ 839 839 'id' => 'free', 840 'name' => ' Media CDN',841 'description' => ' Media CDN Service',840 'name' => 'Trial', 841 'description' => 'Try the Image CDN', 842 842 'highlight' => false, 843 843 'price' => ['cents' => 0, 'formatted' => 'Free', 'period' => null], … … 847 847 'domains' => ['max' => null, 'unlimited' => true], 848 848 ], 849 'features' => ['custom_domain' => true, 'priority_support' => false , 'video_support' => true, 'audio_support' => true],849 'features' => ['custom_domain' => true, 'priority_support' => false], 850 850 ], 851 851 [ 852 'id' => ' unlimited',853 'name' => ' Media CDN',854 'description' => ' Media CDN Service',852 'id' => 'image', 853 'name' => 'Unlimited', 854 'description' => 'Unlimited Image CDN', 855 855 'highlight' => true, 856 'price' => ['cents' => 1999, 'formatted' => '$19.99', 'period' => '/mo'],856 'price' => ['cents' => 999, 'formatted' => '$9.99', 'period' => '/mo'], 857 857 'limits' => [ 858 858 'bandwidth' => ['bytes' => null, 'formatted' => 'Unlimited', 'unlimited' => true], … … 860 860 'domains' => ['max' => null, 'unlimited' => true], 861 861 ], 862 'features' => ['custom_domain' => true, 'priority_support' => true , 'video_support' => true, 'audio_support' => true],862 'features' => ['custom_domain' => true, 'priority_support' => true], 863 863 ], 864 864 ]; … … 882 882 // Fallback defaults (Unlimited tier pricing) 883 883 return [ 884 'amount' => 1999,884 'amount' => 999, 885 885 'currency' => 'USD', 886 886 'interval' => 'month', 887 887 'formatted' => [ 888 'amount' => '$ 19.99',888 'amount' => '$9.99', 889 889 'period' => '/mo', 890 'full' => '$ 19.99/mo',890 'full' => '$9.99/mo', 891 891 ], 892 892 ]; -
bandwidth-saver/tags/1.1/includes/class-imgpro-cdn-onboarding.php
r3446766 r3447384 78 78 // For step 1: only show if no existing subscription 79 79 $tier = $all_settings['cloud_tier'] ?? ''; 80 if (in_array($tier, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_ UNLIMITED, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_ACTIVE], true)) {80 if (in_array($tier, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_IMAGE, ImgPro_CDN_Settings::TIER_UNLIMITED, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_ACTIVE], true)) { 81 81 return false; 82 82 } … … 140 140 * 141 141 * @since 0.1.7 142 * @since 1.1 Updated for Image CDN focus 142 143 * @return void 143 144 */ … … 145 146 ?> 146 147 <div class="imgpro-onboarding-content imgpro-onboarding-step-1"> 147 <h1><?php esc_html_e('Speed up your media', 'bandwidth-saver'); ?></h1>148 <h1><?php esc_html_e('Speed up your images', 'bandwidth-saver'); ?></h1> 148 149 149 150 <p class="imgpro-onboarding-description"> 150 <?php esc_html_e('Slow media hurts your SEO and drives visitors away.', 'bandwidth-saver'); ?><br><?php esc_html_e('Speed itup in 60 seconds.', 'bandwidth-saver'); ?>151 <?php esc_html_e('Slow images hurt your SEO and drive visitors away.', 'bandwidth-saver'); ?><br><?php esc_html_e('Speed them up in 60 seconds.', 'bandwidth-saver'); ?> 151 152 </p> 152 153 … … 158 159 <li> 159 160 <svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M16.667 5L7.5 14.167 3.333 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> 160 <span><strong><?php esc_html_e('Global delivery', 'bandwidth-saver'); ?></strong> — <?php esc_html_e(' media loadsfrom edge servers', 'bandwidth-saver'); ?></span>161 <span><strong><?php esc_html_e('Global delivery', 'bandwidth-saver'); ?></strong> — <?php esc_html_e('images load from edge servers', 'bandwidth-saver'); ?></span> 161 162 </li> 162 163 <li> 163 164 <svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M16.667 5L7.5 14.167 3.333 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> 164 <span><strong><?php esc_html_e('All media types', 'bandwidth-saver'); ?></strong> — <?php esc_html_e('images, video, audio & HLS', 'bandwidth-saver'); ?></span>165 <span><strong><?php esc_html_e('All image formats', 'bandwidth-saver'); ?></strong> — <?php esc_html_e('JPG, PNG, GIF, WebP, AVIF, SVG & more', 'bandwidth-saver'); ?></span> 165 166 </li> 166 167 </ul> … … 185 186 186 187 <p class="imgpro-onboarding-hint"> 187 <?php esc_html_e('$ 19.99/mo to support the service.', 'bandwidth-saver'); ?>188 <?php esc_html_e('$9.99/mo to support the service.', 'bandwidth-saver'); ?> 188 189 <button type="button" class="imgpro-btn-link imgpro-open-plan-selector"><?php esc_html_e('Learn more', 'bandwidth-saver'); ?></button> 189 190 </p> … … 206 207 207 208 <p class="imgpro-onboarding-description"> 208 <?php esc_html_e('Enter your email to set up your MediaCDN.', 'bandwidth-saver'); ?>209 <?php esc_html_e('Enter your email to set up your Image CDN.', 'bandwidth-saver'); ?> 209 210 </p> 210 211 … … 283 284 284 285 <p class="imgpro-onboarding-description"> 285 <?php esc_html_e('Toggle on to start serving mediafrom the CDN.', 'bandwidth-saver'); ?>286 <?php esc_html_e('Toggle on to start serving images from the CDN.', 'bandwidth-saver'); ?> 286 287 </p> 287 288 … … 292 293 </div> 293 294 <div class="imgpro-activate-text"> 294 <strong><?php esc_html_e(' MediaCDN', 'bandwidth-saver'); ?></strong>295 <span><?php esc_html_e('Serve mediafrom edge servers worldwide', 'bandwidth-saver'); ?></span>295 <strong><?php esc_html_e('Image CDN', 'bandwidth-saver'); ?></strong> 296 <span><?php esc_html_e('Serve images from edge servers worldwide', 'bandwidth-saver'); ?></span> 296 297 </div> 297 298 </div> … … 299 300 <input type="checkbox" id="imgpro-activate-toggle"> 300 301 <span class="imgpro-toggle-slider"></span> 301 <span class="screen-reader-text"><?php esc_html_e('Enable MediaCDN', 'bandwidth-saver'); ?></span>302 <span class="screen-reader-text"><?php esc_html_e('Enable Image CDN', 'bandwidth-saver'); ?></span> 302 303 </label> 303 304 </div> … … 308 309 <li> 309 310 <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="3" fill="currentColor"/></svg> 310 <?php esc_html_e(' MediaURLs on your public pages point to the CDN', 'bandwidth-saver'); ?>311 <?php esc_html_e('Image URLs on your public pages point to the CDN', 'bandwidth-saver'); ?> 311 312 </li> 312 313 <li> … … 324 325 <li> 325 326 <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="3" fill="currentColor"/></svg> 326 <?php esc_html_e('If anything goes wrong, media loadsdirectly from your site', 'bandwidth-saver'); ?>327 <?php esc_html_e('If anything goes wrong, images load directly from your site', 'bandwidth-saver'); ?> 327 328 </li> 328 329 </ul> … … 352 353 353 354 <p class="imgpro-onboarding-description"> 354 <?php esc_html_e('Your media isnow being served from edge locations around the world. Visit your site to start caching.', 'bandwidth-saver'); ?>355 <?php esc_html_e('Your images are now being served from edge locations around the world. Visit your site to start caching.', 'bandwidth-saver'); ?> 355 356 </p> 356 357 -
bandwidth-saver/tags/1.1/includes/class-imgpro-cdn-plan-selector.php
r3446766 r3447384 84 84 <?php if (!$is_paid): ?> 85 85 <div class="imgpro-plan-selector__footer"> 86 <button type="button" class="imgpro-btn imgpro-btn-primary imgpro-btn-lg imgpro-btn-full" id="imgpro-plan-checkout" data-tier-id=" unlimited">86 <button type="button" class="imgpro-btn imgpro-btn-primary imgpro-btn-lg imgpro-btn-full" id="imgpro-plan-checkout" data-tier-id="image"> 87 87 <span class="imgpro-btn-text"><?php esc_html_e('Activate Subscription', 'bandwidth-saver'); ?></span> 88 88 <span class="imgpro-btn-loading"> … … 114 114 ?> 115 115 <div class="imgpro-plan-card imgpro-plan-card--single" 116 data-tier-id=" unlimited"116 data-tier-id="image" 117 117 data-tier-name="Unlimited" 118 data-tier-price="$ 19.99/mo">118 data-tier-price="$9.99/mo"> 119 119 120 120 <div class="imgpro-plan-card__header"> 121 <h3 class="imgpro-plan-card__name"><?php esc_html_e(' Media CDN', 'bandwidth-saver'); ?></h3>121 <h3 class="imgpro-plan-card__name"><?php esc_html_e('Unlimited', 'bandwidth-saver'); ?></h3> 122 122 <p class="imgpro-plan-card__description"><?php esc_html_e('Support the service you\'re already using.', 'bandwidth-saver'); ?></p> 123 123 </div> 124 124 125 125 <div class="imgpro-plan-card__price"> 126 <span class="imgpro-plan-card__amount">$ 19.99</span>126 <span class="imgpro-plan-card__amount">$9.99</span> 127 127 <span class="imgpro-plan-card__period">/mo</span> 128 128 </div> … … 139 139 <path d="M13.333 4L6 11.333 2.667 8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> 140 140 </svg> 141 <span><?php esc_html_e(' Images, video, audio & HLS streaming', 'bandwidth-saver'); ?></span>141 <span><?php esc_html_e('All image formats (JPG, PNG, GIF, WebP, AVIF, SVG)', 'bandwidth-saver'); ?></span> 142 142 </li> 143 143 <li class="imgpro-plan-card__feature"> … … 180 180 <h3 class="imgpro-plan-active__title"><?php esc_html_e('Subscription Active', 'bandwidth-saver'); ?></h3> 181 181 <p class="imgpro-plan-active__description"> 182 <?php esc_html_e('Thank you for supporting the MediaCDN. Your subscription keeps the service running.', 'bandwidth-saver'); ?>182 <?php esc_html_e('Thank you for supporting the Image CDN. Your subscription keeps the service running.', 'bandwidth-saver'); ?> 183 183 </p> 184 184 <button type="button" class="imgpro-btn imgpro-btn-secondary" id="imgpro-manage-subscription"> -
bandwidth-saver/tags/1.1/includes/class-imgpro-cdn-rewriter.php
r3446766 r3447384 16 16 * Transforms image URLs to point to CDN, handles context detection, 17 17 * and processes various WordPress image output hooks. 18 * 19 * Image-only architecture (v1.1+): 20 * - Supports images only (JPG, PNG, GIF, WebP, AVIF, SVG, etc.) 21 * - Video/audio not processed - use Unlimited CDN plugin for media 18 22 * 19 23 * Single-domain architecture (v1.1.0+): … … 194 198 * 195 199 * @since 0.1.0 196 * @since 0.2.0 Added video and audio shortcode filters200 * @since 1.1 Removed video/audio filters - Image CDN only 197 201 * @return void 198 202 */ … … 213 217 add_filter('wp_get_attachment_image_attributes', [$this, 'rewrite_attributes'], 999, 3); 214 218 215 // Content filters (processes img , video, audio, source tags)219 // Content filters (processes img tags only - Image CDN) 216 220 add_filter('the_content', [$this, 'rewrite_content'], 999); 217 221 add_filter('post_thumbnail_html', [$this, 'rewrite_content'], 999); 218 222 add_filter('widget_text', [$this, 'rewrite_content'], 999); 219 220 // Video and audio shortcode filters (WordPress media embeds)221 add_filter('wp_video_shortcode', [$this, 'rewrite_content'], 999);222 add_filter('wp_audio_shortcode', [$this, 'rewrite_content'], 999);223 223 } 224 224 … … 417 417 418 418 /** 419 * Build onerror fallback handler for video/audio elements420 *421 * Creates inline JavaScript that falls back to origin URLs on CDN failure.422 * Uses the same URL conversion pattern as get_onerror_handler() for images.423 * Unlike images, video/audio may have multiple source elements that all424 * need to be rewritten, plus a poster attribute for videos.425 *426 * IMPORTANT: Only transforms URLs that were marked as CDN URLs:427 * - this.src only if data-imgpro-cdn is set on the element428 * - this.poster only if data-imgpro-poster is set on the element429 * - source children only if they have data-imgpro-cdn430 * This prevents corrupting non-CDN URLs (e.g., YouTube embeds).431 *432 * @since 1.0433 * @return string JavaScript onerror handler for media elements.434 */435 private function get_media_onerror_handler() {436 // Fallback logic for video/audio (same pattern as images):437 // 1. Check if not already in fallback state438 // 2. Mark as fallback='1' (trying origin)439 // 3. Track if any URLs were transformed440 // 4. Rewrite direct src ONLY if data-imgpro-cdn is set441 // 5. Rewrite all child source elements with data-imgpro-cdn442 // 6. Rewrite poster ONLY if data-imgpro-poster is set443 // 7. Only call load() if something was transformed (avoid unnecessary retries)444 $handler = "if (!this.dataset.fallback) { "445 . "this.dataset.fallback = '1'; "446 . "var changed = false; "447 // Rewrite direct src only if marked as CDN448 . "if (this.src && this.dataset.imgproCdn) { var p = this.src.split('/').slice(3); this.src = 'https://' + p[0] + '/' + p.slice(1).join('/'); changed = true; } "449 // Rewrite source children (only those with data-imgpro-cdn)450 . "var sources = this.querySelectorAll('source[data-imgpro-cdn]'); "451 . "for (var i = 0; i < sources.length; i++) { var sp = sources[i].src.split('/').slice(3); sources[i].src = 'https://' + sp[0] + '/' + sp.slice(1).join('/'); changed = true; } "452 // Rewrite poster only if marked as CDN453 . "if (this.poster && this.dataset.imgproPoster) { var pp = this.poster.split('/').slice(3); this.poster = 'https://' + pp[0] + '/' + pp.slice(1).join('/'); changed = true; } "454 // Only reload if we actually changed something455 . "if (changed) { this.onerror = function() { this.dataset.fallback = '2'; this.onerror = null; }; this.load(); } "456 . "}";457 458 return $handler;459 }460 461 /**462 419 * Rewrite image attributes 463 420 * … … 515 472 * Rewrite content HTML 516 473 * 517 * Processes mediaelements in HTML content that weren't processed by rewrite_attributes()474 * Processes image elements in HTML content that weren't processed by rewrite_attributes() 518 475 * 519 476 * ARCHITECTURE: … … 523 480 * 524 481 * @since 0.1.0 525 * @since 0.2.0 Added video, audio, and source tag support482 * @since 1.1 Simplified to images only - video/audio not processed 526 483 * @param string $content HTML content. 527 484 * @return string … … 538 495 } 539 496 540 // Early bail-out: Skip processing if no mediatags present497 // Early bail-out: Skip processing if no image tags present 541 498 // This is a performance optimization for text-only content 542 $has_ media_tags = false;543 $tag_patterns = ['<img', '<amp-img', '<amp-anim' , '<video', '<audio', '<source'];499 $has_image_tags = false; 500 $tag_patterns = ['<img', '<amp-img', '<amp-anim']; 544 501 545 502 foreach ($tag_patterns as $pattern) { 546 503 if (false !== stripos($content, $pattern)) { 547 $has_ media_tags = true;504 $has_image_tags = true; 548 505 break; 549 506 } 550 507 } 551 508 552 if (!$has_ media_tags) {509 if (!$has_image_tags) { 553 510 return $content; 554 511 } … … 568 525 * Rewrite content using WP_HTML_Tag_Processor (modern approach) 569 526 * 570 * Processes images, videos, audio, and source elements. 571 * 572 * @since 0.1.0 573 * @since 0.2.0 Added video, audio, and source tag support 527 * Processes image elements only (IMG, AMP-IMG, AMP-ANIM). 528 * Video/audio not processed - use Unlimited CDN plugin for media. 529 * 530 * @since 0.1.0 531 * @since 1.1 Simplified to images only 574 532 * @param string $content HTML content. 575 533 * @return string Modified content. … … 578 536 $processor = new WP_HTML_Tag_Processor($content); 579 537 580 // All tags we process538 // Image tags only - video/audio not processed 581 539 $image_tags = ['IMG', 'AMP-IMG', 'AMP-ANIM']; 582 $media_tags = ['VIDEO', 'AUDIO', 'SOURCE'];583 $all_tags = array_merge($image_tags, $media_tags);584 540 585 541 while ($processor->next_tag()) { 586 542 $tag = $processor->get_tag(); 587 543 588 // Skip if not a mediatag589 if (!in_array($tag, $ all_tags, true)) {544 // Skip if not an image tag 545 if (!in_array($tag, $image_tags, true)) { 590 546 continue; 591 547 } … … 609 565 610 566 // Images: add onload for CSS class and onerror for fallback 611 if (in_array($tag, $image_tags, true)) { 612 $processor->set_attribute('onload', $this->get_onload_handler()); 613 $processor->set_attribute('onerror', $this->get_onerror_handler()); 614 } 615 } 616 } 617 618 // VIDEO/AUDIO: Always add onerror handler for CDN fallback 619 // This is needed even without direct src, because: 620 // - WordPress videos typically use <source> children, not src attribute 621 // - The onerror handler rewrites all child sources with data-imgpro-cdn 622 // - If no CDN sources exist, the handler is a harmless no-op 623 // Note: SOURCE elements don't get onerror - error fires on parent media element 624 if ($tag === 'VIDEO' || $tag === 'AUDIO') { 625 $processor->set_attribute('onerror', $this->get_media_onerror_handler()); 626 } 627 628 // VIDEO tag: also process 'poster' attribute (thumbnail image) 629 if ($tag === 'VIDEO') { 630 $poster = $processor->get_attribute('poster'); 631 if (!empty($poster)) { 632 $origin_poster = $this->get_true_origin($poster); 633 if ($this->should_rewrite($origin_poster)) { 634 $processor->set_attribute('poster', esc_url($this->build_cdn_url($origin_poster))); 635 // Mark poster as CDN so onerror handler knows to transform it 636 $processor->set_attribute('data-imgpro-poster', '1'); 637 } 567 $processor->set_attribute('onload', $this->get_onload_handler()); 568 $processor->set_attribute('onerror', $this->get_onerror_handler()); 638 569 } 639 570 } … … 662 593 * 663 594 * @since 0.1.0 664 * @since 0.2.0 Now supports video, audio, and HLS files595 * @since 1.1 Now supports images only (video/audio removed) 665 596 * @param string $url URL to check. 666 597 * @return bool … … 685 616 } 686 617 687 // Must be a supported media file (images, video, audio, HLS)688 if (!$this->is_ media_url($url)) {618 // Must be a supported image file 619 if (!$this->is_image_url($url)) { 689 620 return false; 690 621 } … … 694 625 695 626 /** 696 * Check if URL is a supported mediafile697 * 698 * Supports images, video, audio, and HLS streaming files.627 * Check if URL is a supported image file 628 * 629 * Supports common image formats only. For video/audio, use Unlimited CDN plugin. 699 630 * 700 631 * @since 0.2.0 632 * @since 1.1 Renamed from is_media_url, removed video/audio 701 633 * @param string $url URL to check. 702 * @return bool True if URL points to a supported mediafile.703 */ 704 private function is_ media_url($url) {634 * @return bool True if URL points to a supported image file. 635 */ 636 private function is_image_url($url) { 705 637 /** 706 * Filter the list of allowed mediaextensions638 * Filter the list of allowed image extensions 707 639 * 708 * @since 1. 0640 * @since 1.1 709 641 * @param array $extensions List of file extensions (without dots) 710 642 */ 711 $extensions = apply_filters('imgpro_ media_extensions', [712 // Images 643 $extensions = apply_filters('imgpro_image_extensions', [ 644 // Images only 713 645 'jpg', 'jpeg', 'png', 'gif', 'webp', 'avif', 'svg', 714 646 'bmp', 'tiff', 'ico', 'heic', 'heif', 715 // Video716 'mp4', 'm4v', 'webm', 'ogv', 'mov', 'mkv',717 // Audio718 'mp3', 'ogg', 'wav', 'm4a', 'flac', 'aac', 'weba',719 // HLS720 'm3u8', 'ts',721 647 ]); 722 648 -
bandwidth-saver/tags/1.1/includes/class-imgpro-cdn-settings.php
r3446766 r3447384 85 85 86 86 /** 87 * Subscription tier: Unlimited (paid, $19.99/mo) 88 * 89 * The main paid tier with unlimited bandwidth and cache. 87 * Subscription tier: Image (paid, $9.99/mo) 88 * 89 * The main paid tier for Image CDN with unlimited bandwidth. 90 * 91 * @since 1.1 92 * @var string 93 */ 94 const TIER_IMAGE = 'image'; 95 96 /** 97 * Subscription tier: Unlimited (legacy, for Unlimited CDN plugin) 98 * 99 * Kept for backward compatibility. New Image CDN users use TIER_IMAGE. 90 100 * 91 101 * @since 0.3.0 … … 200 210 * @var string 201 211 */ 202 const API_BASE_URL = 'https:// cloud.wp.img.pro';212 const API_BASE_URL = 'https://billing.bandwidth-saver.com'; 203 213 204 214 /** … … 402 412 if (isset($settings['cloud_tier'])) { 403 413 $tier = sanitize_text_field($settings['cloud_tier']); 404 if (in_array($tier, [self::TIER_NONE, self::TIER_FREE, self::TIER_ LITE, self::TIER_PRO, self::TIER_BUSINESS, self::TIER_UNLIMITED, self::TIER_ACTIVE, self::TIER_CANCELLED, self::TIER_PAST_DUE, self::TIER_SUSPENDED], true)) {414 if (in_array($tier, [self::TIER_NONE, self::TIER_FREE, self::TIER_IMAGE, self::TIER_LITE, self::TIER_PRO, self::TIER_BUSINESS, self::TIER_UNLIMITED, self::TIER_ACTIVE, self::TIER_CANCELLED, self::TIER_PAST_DUE, self::TIER_SUSPENDED], true)) { 405 415 $validated['cloud_tier'] = $tier; 406 416 } … … 739 749 if (self::MODE_CLOUD === $mode) { 740 750 $tier = $settings['cloud_tier'] ?? ''; 741 // Valid tiers: free (trial), unlimited, lite, pro, business (legacy), active (legacy), past_due (grace period)742 return in_array($tier, [self::TIER_FREE, self::TIER_ UNLIMITED, self::TIER_LITE, self::TIER_PRO, self::TIER_BUSINESS, self::TIER_ACTIVE, self::TIER_PAST_DUE], true);751 // Valid tiers: free (trial), image, unlimited, lite, pro, business (legacy), active (legacy), past_due (grace period) 752 return in_array($tier, [self::TIER_FREE, self::TIER_IMAGE, self::TIER_UNLIMITED, self::TIER_LITE, self::TIER_PRO, self::TIER_BUSINESS, self::TIER_ACTIVE, self::TIER_PAST_DUE], true); 743 753 } elseif (self::MODE_CLOUDFLARE === $mode) { 744 754 return !empty($settings['cdn_url']); … … 785 795 786 796 /** 787 * Check if user has any paid subscription ( unlimitedor legacy tiers)797 * Check if user has any paid subscription (image, unlimited, or legacy tiers) 788 798 * 789 799 * @since 0.1.7 … … 794 804 $tier = $settings['cloud_tier'] ?? ''; 795 805 // past_due still counts as paid (grace period) 796 // unlimited is the primary paid tier, legacy tiers (lite, pro, business) still supported 797 return in_array($tier, [self::TIER_UNLIMITED, self::TIER_LITE, self::TIER_PRO, self::TIER_BUSINESS, self::TIER_ACTIVE, self::TIER_PAST_DUE], true); 806 // image is the primary paid tier for Image CDN, unlimited for Unlimited CDN 807 // legacy tiers (lite, pro, business) still supported 808 return in_array($tier, [self::TIER_IMAGE, self::TIER_UNLIMITED, self::TIER_LITE, self::TIER_PRO, self::TIER_BUSINESS, self::TIER_ACTIVE, self::TIER_PAST_DUE], true); 798 809 } 799 810 … … 848 859 849 860 /** 850 * Check if user is on unlimited tier861 * Check if user is on a tier with unlimited bandwidth (image or unlimited) 851 862 * 852 863 * @since 0.3.0 853 864 * @param array $settings The settings array to check against. 854 * @return bool True if user is on unlimited tier.865 * @return bool True if user is on a tier with unlimited bandwidth. 855 866 */ 856 867 public static function is_unlimited($settings) { 857 return self::TIER_UNLIMITED === ($settings['cloud_tier'] ?? ''); 868 $tier = $settings['cloud_tier'] ?? ''; 869 return in_array($tier, [self::TIER_IMAGE, self::TIER_UNLIMITED], true); 858 870 } 859 871 … … 894 906 $tier = $settings['cloud_tier'] ?? ''; 895 907 switch ($tier) { 908 case self::TIER_IMAGE: 896 909 case self::TIER_UNLIMITED: 897 910 return -1; // Unlimited … … 943 956 $tier = $settings['cloud_tier'] ?? ''; 944 957 switch ($tier) { 958 case self::TIER_IMAGE: 945 959 case self::TIER_UNLIMITED: 946 960 return -1; // Unlimited -
bandwidth-saver/tags/1.1/readme.txt
r3446766 r3447384 1 === Bandwidth Saver: Unlimited MediaCDN ===1 === Bandwidth Saver: Image CDN === 2 2 Contributors: imgpro 3 Tags: media cdn, cdn, video cdn, image cdn, hls streaming3 Tags: image cdn, cdn, image optimization, core web vitals, page speed 4 4 Requires at least: 6.2 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 1. 07 Stable tag: 1.1 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 10 11 Unlimited media CDN for WordPress. Serve images, video, audio, and HLS streams from 300+ edge servers. $19.99/mo for unlimited bandwidth.11 Image CDN for WordPress. Serve images from 300+ global edge servers. Faster Core Web Vitals, better SEO. $9.99/mo. 12 12 13 13 == Description == 14 14 15 ** Unlimited mediaCDN that makes your WordPress site faster.**16 17 Heavy media files slow down your site. When videos buffer andimages lag, visitors leave, Core Web Vitals fail, and Google ranks you lower.18 19 This media CDN plugin fixes that by serving your images, videos, audio, and HLS streams from 300+ global edge servers. A visitor in Tokyo loads mediafrom Asia. A visitor in London loads from Europe. Everyone gets faster pages.15 **Image CDN that makes your WordPress site faster.** 16 17 Heavy images slow down your site. When images lag, visitors leave, Core Web Vitals fail, and Google ranks you lower. 18 19 This image CDN plugin fixes that by serving your images from 300+ global edge servers. A visitor in Tokyo loads images from Asia. A visitor in London loads from Europe. Everyone gets faster pages. 20 20 21 21 **60-second setup.** No DNS changes. No external accounts. No settings to configure. Just activate and start delivering. 22 22 23 = Why Use a MediaCDN? =24 25 * **Faster page load times** — Media loadsfrom the nearest server instead of traveling across the world from your host23 = Why Use an Image CDN? = 24 25 * **Faster page load times** — Images load from the nearest server instead of traveling across the world from your host 26 26 * **Better Core Web Vitals** — Improve LCP (Largest Contentful Paint) by delivering images faster 27 * **Smooth video playback** — HLS streaming and video files buffer less with edge delivery28 27 * **Higher PageSpeed scores** — Google PageSpeed Insights will show improved performance 29 28 * **Lower bounce rates** — Visitors don't wait for slow sites 30 31 = All Media Types Supported = 32 33 * **Images** — JPG, PNG, GIF, WebP, AVIF, SVG 34 * **Video** — MP4, WebM, MOV with range request support 35 * **Audio** — MP3, WAV, OGG, FLAC 36 * **HLS Streaming** — M3U8 playlists and TS segments 37 38 = How This Media CDN Works = 39 40 1. Install the media CDN plugin from WordPress 29 * **Better SEO** — Speed is a ranking factor 30 31 = All Image Formats Supported = 32 33 * **Standard** — JPG, JPEG, PNG, GIF 34 * **Modern** — WebP, AVIF 35 * **Vector** — SVG 36 * **Other** — BMP, TIFF, ICO, HEIC, HEIF 37 38 = How This Image CDN Works = 39 40 1. Install the image CDN plugin from WordPress 41 41 2. Flip the switch to activate 42 3. Media instantly loadsfrom 300+ global CDN servers42 3. Images instantly load from 300+ global CDN servers 43 43 44 44 That's it. Your original files stay exactly where they are on your server. The plugin only changes URLs on your public pages. Deactivate it and everything returns to normal instantly. 45 45 46 = Unlimited Media CDNPricing =47 48 **Unlimited** ($ 19.99/mo)46 = Pricing = 47 48 **Unlimited** ($9.99/mo) 49 49 * Unlimited bandwidth 50 50 * Custom CDN domain (cdn.yoursite.com) 51 51 * Priority support 52 * Images, video, audio, and HLS streaming52 * All image formats 53 53 54 54 All plans include a 7-day money-back guarantee. … … 56 56 = Self-Hosted Option = 57 57 58 For developers who want full control, you can deploy the open-source worker on your own Cloudflare account. Your media, your infrastructure, zero external dependencies.58 For developers who want full control, you can deploy the open-source worker on your own Cloudflare account. Your images, your infrastructure, zero external dependencies. 59 59 60 60 [Self-hosted CDN setup guide on GitHub](https://github.com/img-pro/bandwidth-saver-worker) … … 62 62 = Works With Any WordPress Theme or Plugin = 63 63 64 This mediaCDN is compatible with:64 This image CDN is compatible with: 65 65 66 66 * **Page builders** — Elementor, Divi, Beaver Builder, Gutenberg, Bricks, Oxygen 67 67 * **WooCommerce** — Product images, galleries, thumbnails 68 * **Video players** — Plyr, VideoJS, native HTML5 video69 68 * **Lazy loading** — Works with native lazy load and plugins 70 69 * **Responsive images** — Full srcset support 71 70 * **Caching plugins** — WP Rocket, LiteSpeed Cache, W3 Total Cache, WP Super Cache 72 73 = Who This Media CDN Is For = 74 75 * Video course creators and membership sites 76 * Podcasters and audio content creators 71 * **Image optimization** — ShortPixel, Imagify, Smush, EWWW 72 73 = Who This Image CDN Is For = 74 77 75 * Bloggers with image-heavy posts 78 * WooCommerce stores with product photos and videos76 * WooCommerce stores with product photos 79 77 * Recipe, travel, and photography sites 80 78 * Portfolio and agency sites 81 * Anyone who wants faster WordPress media loading without complexity 79 * Anyone who wants faster WordPress image loading without complexity 80 81 = Need Video/Audio CDN? = 82 83 This plugin focuses on images for simplicity and cost-effectiveness. If you need video, audio, or HLS streaming support, check out our [Unlimited CDN plugin](https://wordpress.org/plugins/unlimited-cdn/) which supports all media types. 82 84 83 85 == Installation == … … 85 87 **60-second setup. No technical knowledge required.** 86 88 87 1. Install and activate the mediaCDN plugin89 1. Install and activate the image CDN plugin 88 90 2. Go to **Settings > Bandwidth Saver** 89 91 3. Toggle the CDN switch on 90 4. Upgrade to Unlimited for $ 19.99/mo91 92 Done. Your media isnow loading faster from the global CDN.92 4. Upgrade to Unlimited for $9.99/mo 93 94 Done. Your images are now loading faster from the global CDN. 93 95 94 96 == Frequently Asked Questions == 95 97 96 = What media types does this CDN support? = 97 98 The media CDN supports all common media formats: images (JPG, PNG, GIF, WebP, AVIF, SVG), video (MP4, WebM, MOV), audio (MP3, WAV, OGG, FLAC), and HLS streaming (M3U8 playlists and TS segments). 99 100 = Will this media CDN improve my Core Web Vitals? = 101 102 Yes. The media CDN improves LCP (Largest Contentful Paint) by serving media from servers close to your visitors. Faster media delivery means better Core Web Vitals scores. 103 104 = How does video streaming work? = 105 106 The CDN supports HTTP range requests, which means video files can be seeked and streamed without downloading the entire file. HLS streams work seamlessly with M3U8 playlist and TS segment delivery. 98 = What image formats does this CDN support? = 99 100 The image CDN supports all common image formats: JPG, JPEG, PNG, GIF, WebP, AVIF, SVG, BMP, TIFF, ICO, HEIC, and HEIF. 101 102 = Will this image CDN improve my Core Web Vitals? = 103 104 Yes. The image CDN improves LCP (Largest Contentful Paint) by serving images from servers close to your visitors. Faster image delivery means better Core Web Vitals scores. 107 105 108 106 = Does the CDN work with WooCommerce? = 109 107 110 Yes. The media CDN works with WooCommerce product images, galleries, thumbnails, and product videos.108 Yes. The image CDN works with WooCommerce product images, galleries, and thumbnails. 111 109 112 110 = Will this CDN work with my page builder? = 113 111 114 Yes. This mediaCDN works with Elementor, Divi, Beaver Builder, Gutenberg blocks, Bricks, Oxygen, and any other WordPress page builder.112 Yes. This image CDN works with Elementor, Divi, Beaver Builder, Gutenberg blocks, Bricks, Oxygen, and any other WordPress page builder. 115 113 116 114 = Is there a file size limit? = 117 115 118 Files up to 500 MB are supported. This covers most images and many video files. For very large video files, consider dedicated video hosting.116 Files up to 500 MB are supported. This covers all typical image sizes. 119 117 120 118 = Can I use my own domain for CDN URLs? = … … 122 120 Yes. The Unlimited plan supports custom domains (cdn.yoursite.com) with automatic SSL. 123 121 124 = What happens if the mediaCDN goes down? =125 126 Your site automatically serves media directly from your server. Visitors won't notice anything — media just loadsthe normal way until the CDN is back.127 128 = Is this mediaCDN safe? Will it break my site? =129 130 The media CDN cannot break your site. Your original files stay on your server completely untouched. The plugin only changes URLs on your public pages. If the CDN ever has issues, your site automatically falls back to loading mediadirectly. Deactivate the plugin and everything returns to normal instantly.122 = What happens if the image CDN goes down? = 123 124 Your site automatically serves images directly from your server. Visitors won't notice anything — images just load the normal way until the CDN is back. 125 126 = Is this image CDN safe? Will it break my site? = 127 128 The image CDN cannot break your site. Your original files stay on your server completely untouched. The plugin only changes URLs on your public pages. If the CDN ever has issues, your site automatically falls back to loading images directly. Deactivate the plugin and everything returns to normal instantly. 131 129 132 130 = Do I need to change my DNS for this CDN? = 133 131 134 No. Unlike other CDN services, this media CDN works immediately without any DNS changes. Everything happens from your WordPress admin. 132 No. Unlike other CDN services, this image CDN works immediately without any DNS changes. Everything happens from your WordPress admin. 133 134 = Does this support video or audio? = 135 136 No. This plugin focuses on images only for simplicity and cost-effectiveness. If you need video, audio, or HLS streaming support, check out the [Unlimited CDN plugin](https://wordpress.org/plugins/unlimited-cdn/). 135 137 136 138 == Screenshots == 137 139 138 1. Speed up your media in 60 seconds with the unlimited mediaCDN140 1. Speed up your images in 60 seconds with the Image CDN 139 141 2. Track your CDN requests and performance 140 142 3. Multi-site support and custom CDN domains … … 145 147 = What Data Is Collected? = 146 148 147 The mediaCDN plugin does not add cookies, tracking pixels, or analytics to your site.149 The image CDN plugin does not add cookies, tracking pixels, or analytics to your site. 148 150 149 151 = Managed Mode = … … 153 155 * Custom domain settings are sent if configured 154 156 155 Media iscached and served through a global edge network powered by Cloudflare.157 Images are cached and served through a global edge network powered by Cloudflare. 156 158 157 159 = Self-Hosted Mode = 158 160 159 No data is sent to us. Media iscached in your own Cloudflare account.161 No data is sent to us. Images are cached in your own Cloudflare account. 160 162 161 163 == External Services == 162 164 163 This mediaCDN plugin connects to external services:165 This image CDN plugin connects to external services: 164 166 165 167 **Cloudflare (R2 Storage and Workers)** 166 168 167 * Purpose: Mediacaching and global edge CDN delivery169 * Purpose: Image caching and global edge CDN delivery 168 170 * [Terms of Service](https://www.cloudflare.com/terms/) 169 171 * [Privacy Policy](https://www.cloudflare.com/privacypolicy/) … … 180 182 This service is provided on a fair use basis. While we don't impose hard limits, we reserve the right to contact users with exceptionally high usage to discuss dedicated plans or custom arrangements. 181 183 182 The 500 MB per-file size limit applies to all media. For larger files or specialized requirements, please contact us to discuss options.183 184 We aim to provide reliable service for legitimate WordPress mediadelivery. Abuse, excessive automated requests, or use that degrades service for others may result in account review.184 The 500 MB per-file size limit applies to all images. For larger files or specialized requirements, please contact us to discuss options. 185 186 We aim to provide reliable service for legitimate WordPress image delivery. Abuse, excessive automated requests, or use that degrades service for others may result in account review. 185 187 186 188 == Changelog == 189 190 = 1.1 = 191 * Changed: Converted from Media CDN to Image CDN 192 * Removed: Video, audio, and HLS streaming support (use Unlimited CDN plugin instead) 193 * Simplified: Image-only focus for better positioning and simpler codebase 194 * Updated: All UI text and documentation for Image CDN 187 195 188 196 = 1.0 = 189 197 * New: Rebranded as "Bandwidth Saver: Unlimited Media CDN" 190 * New: Simplified pricing - single Unlimited tier at $ 19.99/mo198 * New: Simplified pricing - single Unlimited tier at $9.99/mo 191 199 * New: Video and audio CDN support with range requests 192 200 * New: HLS streaming support (M3U8 and TS segments) … … 206 214 207 215 = 0.2.3 = 208 * Improved: Clearer messaging about mediaCDN speed and Core Web Vitals benefits216 * Improved: Clearer messaging about CDN speed and Core Web Vitals benefits 209 217 * Improved: Simplified onboarding copy 210 218 * Improved: Updated screenshot captions … … 213 221 == Upgrade Notice == 214 222 215 = 1. 0=216 Major update: Now supports video, audio, and HLS streaming. New simplified pricing at $19.99/mo for unlimited bandwidth.223 = 1.1 = 224 Breaking change: Video, audio, and HLS streaming no longer supported. If you use video/audio CDN, install the Unlimited CDN plugin instead before upgrading. 217 225 218 226 == Support == -
bandwidth-saver/trunk/admin/js/imgpro-cdn-admin.js
r3446766 r3447384 446 446 447 447 const originalText = $button.text(); 448 // Get tier from parameter, button data attribute, or default to ' unlimited'449 const tier = tierId || $button.data('tier') || ' unlimited';448 // Get tier from parameter, button data attribute, or default to 'image' 449 const tier = tierId || $button.data('tier') || 'image'; 450 450 $button.addClass('is-loading').prop('disabled', true).text(imgproCdnAdmin.i18n.creatingCheckout); 451 451 -
bandwidth-saver/trunk/imgpro-cdn.php
r3446766 r3447384 1 1 <?php 2 2 /** 3 * Plugin Name: Bandwidth Saver: Unlimited MediaCDN3 * Plugin Name: Bandwidth Saver: Image CDN 4 4 * Plugin URI: https://github.com/img-pro/bandwidth-saver 5 * Description: Unlimited media CDN for images, video, audio, and HLS streaming. $19.99/mo for unlimited bandwidth.6 * Version: 1. 05 * Description: Image CDN for WordPress. Serve images from 300+ global edge servers. Faster Core Web Vitals, better SEO. $9.99/mo. 6 * Version: 1.1 7 7 * Author: ImgPro 8 8 * Author URI: https://img.pro … … 47 47 // Define plugin constants 48 48 if (!defined('IMGPRO_CDN_VERSION')) { 49 define('IMGPRO_CDN_VERSION', '1. 0');49 define('IMGPRO_CDN_VERSION', '1.1'); 50 50 } 51 51 if (!defined('IMGPRO_CDN_PLUGIN_DIR')) { … … 90 90 function imgpro_cdn_add_version_html() { 91 91 if (!is_admin()) { 92 echo "\n<!-- MediaCDN by ImgPro v" . esc_attr(IMGPRO_CDN_VERSION) . " -->\n";92 echo "\n<!-- Image CDN by ImgPro v" . esc_attr(IMGPRO_CDN_VERSION) . " -->\n"; 93 93 } 94 94 } -
bandwidth-saver/trunk/includes/class-imgpro-cdn-admin-ajax.php
r3446766 r3447384 293 293 if ($current_enabled === $enabled) { 294 294 $message = $enabled 295 ? __(' Media CDN is active. Media isloading from Cloudflare.', 'bandwidth-saver')296 : __(' Media CDN is disabled. Media isloading from your server.', 'bandwidth-saver');295 ? __('Image CDN is active. Images are loading from Cloudflare.', 'bandwidth-saver') 296 : __('Image CDN is disabled. Images are loading from your server.', 'bandwidth-saver'); 297 297 298 298 wp_send_json_success(['message' => $message]); … … 313 313 if (false !== $result) { 314 314 $message = $enabled 315 ? __(' Media CDN enabled. Media now loadsfrom the global network.', 'bandwidth-saver')316 : __(' Media CDN disabled. Media now loadsfrom your server.', 'bandwidth-saver');315 ? __('Image CDN enabled. Images now load from the global network.', 'bandwidth-saver') 316 : __('Image CDN disabled. Images now load from your server.', 'bandwidth-saver'); 317 317 318 318 $response = ['message' => $message]; … … 600 600 ImgPro_CDN_Security::check_rate_limit('checkout'); 601 601 602 // Always upgrade to unlimited tier (single paid tier model)602 // Always upgrade to image tier (single paid tier model for Image CDN) 603 603 // tier_id parameter kept for backwards compatibility but ignored 604 $tier_id = ' unlimited';604 $tier_id = 'image'; 605 605 606 606 // SECURITY: Use get_api_key() to decrypt the stored API key … … 779 779 // Enable CDN if valid subscription 780 780 $current_tier_id = $this->api->get_tier_id($site); 781 if (in_array($current_tier_id, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_ UNLIMITED, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE], true)) {781 if (in_array($current_tier_id, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_IMAGE, ImgPro_CDN_Settings::TIER_UNLIMITED, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE], true)) { 782 782 $this->settings->update([ 783 783 'cloud_enabled' => true, … … 797 797 ImgPro_CDN_Settings::TIER_PRO => 3, 798 798 ImgPro_CDN_Settings::TIER_BUSINESS => 4, 799 ImgPro_CDN_Settings::TIER_IMAGE => 5, 799 800 ImgPro_CDN_Settings::TIER_UNLIMITED => 5, 800 801 ]; … … 1056 1057 1057 1058 wp_send_json_success([ 1058 'message' => __('CDN domain removed. The MediaCDN has been disabled.', 'bandwidth-saver')1059 'message' => __('CDN domain removed. The Image CDN has been disabled.', 'bandwidth-saver') 1059 1060 ]); 1060 1061 } … … 1117 1118 $tier_valid = in_array($tier, [ 1118 1119 ImgPro_CDN_Settings::TIER_FREE, 1120 ImgPro_CDN_Settings::TIER_IMAGE, 1119 1121 ImgPro_CDN_Settings::TIER_UNLIMITED, 1120 1122 ImgPro_CDN_Settings::TIER_LITE, … … 1418 1420 'count' => $full_response['count'] ?? count($source_urls), 1419 1421 'max_domains' => -1, // Unlimited for all users 1420 'tier_name' => $full_response['tier_name'] ?? ' Media CDN'1422 'tier_name' => $full_response['tier_name'] ?? 'Unlimited' 1421 1423 ]); 1422 1424 } -
bandwidth-saver/trunk/includes/class-imgpro-cdn-admin.php
r3446766 r3447384 159 159 // Enable if subscription is valid 160 160 $tier_id = $this->api->get_tier_id($site); 161 $valid_tiers = [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_ UNLIMITED, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE];161 $valid_tiers = [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_IMAGE, ImgPro_CDN_Settings::TIER_UNLIMITED, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE]; 162 162 163 163 if (in_array($tier_id, $valid_tiers, true)) { … … 468 468 // Toggle UI text 469 469 'cdnActiveHeading' => __('Your media is loading faster', 'bandwidth-saver'), 470 'cdnInactiveHeading' => __(' MediaCDN is Off', 'bandwidth-saver'),470 'cdnInactiveHeading' => __('Image CDN is Off', 'bandwidth-saver'), 471 471 'cdnActiveDesc' => __('Visitors worldwide are getting faster page loads.', 'bandwidth-saver'), 472 472 'cdnInactiveDesc' => __('Turn on to speed up your media.', 'bandwidth-saver'), … … 479 479 'domainActive' => __('Custom domain is active.', 'bandwidth-saver'), 480 480 'confirmRemoveDomain' => __('Remove this custom domain? Media will be served from the default domain.', 'bandwidth-saver'), 481 'confirmRemoveCdnDomain' => __('Remove this CDN domain? The MediaCDN will be disabled.', 'bandwidth-saver'),481 'confirmRemoveCdnDomain' => __('Remove this CDN domain? The Image CDN will be disabled.', 'bandwidth-saver'), 482 482 'cdnDomainRemoved' => __('CDN domain removed.', 'bandwidth-saver'), 483 483 // Upgrade prompts … … 821 821 <h2 id="imgpro-toggle-heading"> 822 822 <?php echo $is_enabled 823 ? esc_html__('Your media isloading faster', 'bandwidth-saver')824 : esc_html__(' MediaCDN is Off', 'bandwidth-saver'); ?>823 ? esc_html__('Your images are loading faster', 'bandwidth-saver') 824 : esc_html__('Image CDN is Off', 'bandwidth-saver'); ?> 825 825 </h2> 826 826 <p id="imgpro-toggle-description"> 827 827 <?php echo $is_enabled 828 828 ? esc_html__('Visitors worldwide are getting faster page loads.', 'bandwidth-saver') 829 : esc_html__('Turn on to speed up your media.', 'bandwidth-saver'); ?>829 : esc_html__('Turn on to speed up your images.', 'bandwidth-saver'); ?> 830 830 </p> 831 831 </div> … … 843 843 > 844 844 <span class="imgpro-toggle-slider"></span> 845 <span class="screen-reader-text"><?php esc_html_e('Toggle MediaCDN', 'bandwidth-saver'); ?></span>845 <span class="screen-reader-text"><?php esc_html_e('Toggle Image CDN', 'bandwidth-saver'); ?></span> 846 846 </label> 847 847 </div> … … 1163 1163 private function render_cloud_tab($settings) { 1164 1164 $tier = $settings['cloud_tier'] ?? ImgPro_CDN_Settings::TIER_NONE; 1165 $has_subscription = in_array($tier, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_ UNLIMITED, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE, ImgPro_CDN_Settings::TIER_PAST_DUE], true);1165 $has_subscription = in_array($tier, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_IMAGE, ImgPro_CDN_Settings::TIER_UNLIMITED, ImgPro_CDN_Settings::TIER_LITE, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_BUSINESS, ImgPro_CDN_Settings::TIER_ACTIVE, ImgPro_CDN_Settings::TIER_PAST_DUE], true); 1166 1166 ?> 1167 1167 <div class="imgpro-tab-panel" role="tabpanel"> … … 1285 1285 <span class="imgpro-account-card__status-text"><?php esc_html_e('Subscription Active', 'bandwidth-saver'); ?></span> 1286 1286 </div> 1287 <span class="imgpro-account-card__description"><?php esc_html_e('Unlimited mediadelivery from 300+ edge servers.', 'bandwidth-saver'); ?></span>1287 <span class="imgpro-account-card__description"><?php esc_html_e('Unlimited image delivery from 300+ edge servers.', 'bandwidth-saver'); ?></span> 1288 1288 <?php else: ?> 1289 <strong class="imgpro-account-card__headline"><?php esc_html_e('Enjoying the MediaCDN?', 'bandwidth-saver'); ?></strong>1289 <strong class="imgpro-account-card__headline"><?php esc_html_e('Enjoying the Image CDN?', 'bandwidth-saver'); ?></strong> 1290 1290 <span class="imgpro-account-card__description"><?php esc_html_e('Activate your subscription to support continued development.', 'bandwidth-saver'); ?></span> 1291 1291 <?php endif; ?> … … 1310 1310 <?php if ($is_paid && !empty($email)): ?> 1311 1311 <span class="imgpro-separator">·</span> 1312 <span class="imgpro-account-card__price"><?php esc_html_e('$ 19.99/mo', 'bandwidth-saver'); ?></span>1312 <span class="imgpro-account-card__price"><?php esc_html_e('$9.99/mo', 'bandwidth-saver'); ?></span> 1313 1313 <?php elseif (!$is_paid): ?> 1314 1314 <?php if (!empty($email)): ?> 1315 1315 <span class="imgpro-separator">·</span> 1316 1316 <?php endif; ?> 1317 <span class="imgpro-account-card__price"><?php esc_html_e('$ 19.99/mo', 'bandwidth-saver'); ?></span>1317 <span class="imgpro-account-card__price"><?php esc_html_e('$9.99/mo', 'bandwidth-saver'); ?></span> 1318 1318 <?php endif; ?> 1319 1319 </div> -
bandwidth-saver/trunk/includes/class-imgpro-cdn-api.php
r3446766 r3447384 26 26 * @var string 27 27 */ 28 const BASE_URL = 'https:// cloud.wp.img.pro';28 const BASE_URL = 'https://billing.bandwidth-saver.com'; 29 29 30 30 /** … … 336 336 * 337 337 * @param string $api_key Site API key. 338 * @param string $tier_id Target tier ID (default: ' unlimited').338 * @param string $tier_id Target tier ID (default: 'image'). 339 339 * @return array|WP_Error Checkout data with URL or error. 340 340 */ 341 public function create_checkout($api_key, $tier_id = ' unlimited') {341 public function create_checkout($api_key, $tier_id = 'image') { 342 342 if (empty($api_key)) { 343 343 return new WP_Error('missing_api_key', __('API key is required', 'bandwidth-saver')); … … 838 838 [ 839 839 'id' => 'free', 840 'name' => ' Media CDN',841 'description' => ' Media CDN Service',840 'name' => 'Trial', 841 'description' => 'Try the Image CDN', 842 842 'highlight' => false, 843 843 'price' => ['cents' => 0, 'formatted' => 'Free', 'period' => null], … … 847 847 'domains' => ['max' => null, 'unlimited' => true], 848 848 ], 849 'features' => ['custom_domain' => true, 'priority_support' => false , 'video_support' => true, 'audio_support' => true],849 'features' => ['custom_domain' => true, 'priority_support' => false], 850 850 ], 851 851 [ 852 'id' => ' unlimited',853 'name' => ' Media CDN',854 'description' => ' Media CDN Service',852 'id' => 'image', 853 'name' => 'Unlimited', 854 'description' => 'Unlimited Image CDN', 855 855 'highlight' => true, 856 'price' => ['cents' => 1999, 'formatted' => '$19.99', 'period' => '/mo'],856 'price' => ['cents' => 999, 'formatted' => '$9.99', 'period' => '/mo'], 857 857 'limits' => [ 858 858 'bandwidth' => ['bytes' => null, 'formatted' => 'Unlimited', 'unlimited' => true], … … 860 860 'domains' => ['max' => null, 'unlimited' => true], 861 861 ], 862 'features' => ['custom_domain' => true, 'priority_support' => true , 'video_support' => true, 'audio_support' => true],862 'features' => ['custom_domain' => true, 'priority_support' => true], 863 863 ], 864 864 ]; … … 882 882 // Fallback defaults (Unlimited tier pricing) 883 883 return [ 884 'amount' => 1999,884 'amount' => 999, 885 885 'currency' => 'USD', 886 886 'interval' => 'month', 887 887 'formatted' => [ 888 'amount' => '$ 19.99',888 'amount' => '$9.99', 889 889 'period' => '/mo', 890 'full' => '$ 19.99/mo',890 'full' => '$9.99/mo', 891 891 ], 892 892 ]; -
bandwidth-saver/trunk/includes/class-imgpro-cdn-onboarding.php
r3446766 r3447384 78 78 // For step 1: only show if no existing subscription 79 79 $tier = $all_settings['cloud_tier'] ?? ''; 80 if (in_array($tier, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_ UNLIMITED, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_ACTIVE], true)) {80 if (in_array($tier, [ImgPro_CDN_Settings::TIER_FREE, ImgPro_CDN_Settings::TIER_IMAGE, ImgPro_CDN_Settings::TIER_UNLIMITED, ImgPro_CDN_Settings::TIER_PRO, ImgPro_CDN_Settings::TIER_ACTIVE], true)) { 81 81 return false; 82 82 } … … 140 140 * 141 141 * @since 0.1.7 142 * @since 1.1 Updated for Image CDN focus 142 143 * @return void 143 144 */ … … 145 146 ?> 146 147 <div class="imgpro-onboarding-content imgpro-onboarding-step-1"> 147 <h1><?php esc_html_e('Speed up your media', 'bandwidth-saver'); ?></h1>148 <h1><?php esc_html_e('Speed up your images', 'bandwidth-saver'); ?></h1> 148 149 149 150 <p class="imgpro-onboarding-description"> 150 <?php esc_html_e('Slow media hurts your SEO and drives visitors away.', 'bandwidth-saver'); ?><br><?php esc_html_e('Speed itup in 60 seconds.', 'bandwidth-saver'); ?>151 <?php esc_html_e('Slow images hurt your SEO and drive visitors away.', 'bandwidth-saver'); ?><br><?php esc_html_e('Speed them up in 60 seconds.', 'bandwidth-saver'); ?> 151 152 </p> 152 153 … … 158 159 <li> 159 160 <svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M16.667 5L7.5 14.167 3.333 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> 160 <span><strong><?php esc_html_e('Global delivery', 'bandwidth-saver'); ?></strong> — <?php esc_html_e(' media loadsfrom edge servers', 'bandwidth-saver'); ?></span>161 <span><strong><?php esc_html_e('Global delivery', 'bandwidth-saver'); ?></strong> — <?php esc_html_e('images load from edge servers', 'bandwidth-saver'); ?></span> 161 162 </li> 162 163 <li> 163 164 <svg width="20" height="20" viewBox="0 0 20 20" fill="none"><path d="M16.667 5L7.5 14.167 3.333 10" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg> 164 <span><strong><?php esc_html_e('All media types', 'bandwidth-saver'); ?></strong> — <?php esc_html_e('images, video, audio & HLS', 'bandwidth-saver'); ?></span>165 <span><strong><?php esc_html_e('All image formats', 'bandwidth-saver'); ?></strong> — <?php esc_html_e('JPG, PNG, GIF, WebP, AVIF, SVG & more', 'bandwidth-saver'); ?></span> 165 166 </li> 166 167 </ul> … … 185 186 186 187 <p class="imgpro-onboarding-hint"> 187 <?php esc_html_e('$ 19.99/mo to support the service.', 'bandwidth-saver'); ?>188 <?php esc_html_e('$9.99/mo to support the service.', 'bandwidth-saver'); ?> 188 189 <button type="button" class="imgpro-btn-link imgpro-open-plan-selector"><?php esc_html_e('Learn more', 'bandwidth-saver'); ?></button> 189 190 </p> … … 206 207 207 208 <p class="imgpro-onboarding-description"> 208 <?php esc_html_e('Enter your email to set up your MediaCDN.', 'bandwidth-saver'); ?>209 <?php esc_html_e('Enter your email to set up your Image CDN.', 'bandwidth-saver'); ?> 209 210 </p> 210 211 … … 283 284 284 285 <p class="imgpro-onboarding-description"> 285 <?php esc_html_e('Toggle on to start serving mediafrom the CDN.', 'bandwidth-saver'); ?>286 <?php esc_html_e('Toggle on to start serving images from the CDN.', 'bandwidth-saver'); ?> 286 287 </p> 287 288 … … 292 293 </div> 293 294 <div class="imgpro-activate-text"> 294 <strong><?php esc_html_e(' MediaCDN', 'bandwidth-saver'); ?></strong>295 <span><?php esc_html_e('Serve mediafrom edge servers worldwide', 'bandwidth-saver'); ?></span>295 <strong><?php esc_html_e('Image CDN', 'bandwidth-saver'); ?></strong> 296 <span><?php esc_html_e('Serve images from edge servers worldwide', 'bandwidth-saver'); ?></span> 296 297 </div> 297 298 </div> … … 299 300 <input type="checkbox" id="imgpro-activate-toggle"> 300 301 <span class="imgpro-toggle-slider"></span> 301 <span class="screen-reader-text"><?php esc_html_e('Enable MediaCDN', 'bandwidth-saver'); ?></span>302 <span class="screen-reader-text"><?php esc_html_e('Enable Image CDN', 'bandwidth-saver'); ?></span> 302 303 </label> 303 304 </div> … … 308 309 <li> 309 310 <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="3" fill="currentColor"/></svg> 310 <?php esc_html_e(' MediaURLs on your public pages point to the CDN', 'bandwidth-saver'); ?>311 <?php esc_html_e('Image URLs on your public pages point to the CDN', 'bandwidth-saver'); ?> 311 312 </li> 312 313 <li> … … 324 325 <li> 325 326 <svg width="16" height="16" viewBox="0 0 16 16" fill="none"><circle cx="8" cy="8" r="3" fill="currentColor"/></svg> 326 <?php esc_html_e('If anything goes wrong, media loadsdirectly from your site', 'bandwidth-saver'); ?>327 <?php esc_html_e('If anything goes wrong, images load directly from your site', 'bandwidth-saver'); ?> 327 328 </li> 328 329 </ul> … … 352 353 353 354 <p class="imgpro-onboarding-description"> 354 <?php esc_html_e('Your media isnow being served from edge locations around the world. Visit your site to start caching.', 'bandwidth-saver'); ?>355 <?php esc_html_e('Your images are now being served from edge locations around the world. Visit your site to start caching.', 'bandwidth-saver'); ?> 355 356 </p> 356 357 -
bandwidth-saver/trunk/includes/class-imgpro-cdn-plan-selector.php
r3446766 r3447384 84 84 <?php if (!$is_paid): ?> 85 85 <div class="imgpro-plan-selector__footer"> 86 <button type="button" class="imgpro-btn imgpro-btn-primary imgpro-btn-lg imgpro-btn-full" id="imgpro-plan-checkout" data-tier-id=" unlimited">86 <button type="button" class="imgpro-btn imgpro-btn-primary imgpro-btn-lg imgpro-btn-full" id="imgpro-plan-checkout" data-tier-id="image"> 87 87 <span class="imgpro-btn-text"><?php esc_html_e('Activate Subscription', 'bandwidth-saver'); ?></span> 88 88 <span class="imgpro-btn-loading"> … … 114 114 ?> 115 115 <div class="imgpro-plan-card imgpro-plan-card--single" 116 data-tier-id=" unlimited"116 data-tier-id="image" 117 117 data-tier-name="Unlimited" 118 data-tier-price="$ 19.99/mo">118 data-tier-price="$9.99/mo"> 119 119 120 120 <div class="imgpro-plan-card__header"> 121 <h3 class="imgpro-plan-card__name"><?php esc_html_e(' Media CDN', 'bandwidth-saver'); ?></h3>121 <h3 class="imgpro-plan-card__name"><?php esc_html_e('Unlimited', 'bandwidth-saver'); ?></h3> 122 122 <p class="imgpro-plan-card__description"><?php esc_html_e('Support the service you\'re already using.', 'bandwidth-saver'); ?></p> 123 123 </div> 124 124 125 125 <div class="imgpro-plan-card__price"> 126 <span class="imgpro-plan-card__amount">$ 19.99</span>126 <span class="imgpro-plan-card__amount">$9.99</span> 127 127 <span class="imgpro-plan-card__period">/mo</span> 128 128 </div> … … 139 139 <path d="M13.333 4L6 11.333 2.667 8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/> 140 140 </svg> 141 <span><?php esc_html_e(' Images, video, audio & HLS streaming', 'bandwidth-saver'); ?></span>141 <span><?php esc_html_e('All image formats (JPG, PNG, GIF, WebP, AVIF, SVG)', 'bandwidth-saver'); ?></span> 142 142 </li> 143 143 <li class="imgpro-plan-card__feature"> … … 180 180 <h3 class="imgpro-plan-active__title"><?php esc_html_e('Subscription Active', 'bandwidth-saver'); ?></h3> 181 181 <p class="imgpro-plan-active__description"> 182 <?php esc_html_e('Thank you for supporting the MediaCDN. Your subscription keeps the service running.', 'bandwidth-saver'); ?>182 <?php esc_html_e('Thank you for supporting the Image CDN. Your subscription keeps the service running.', 'bandwidth-saver'); ?> 183 183 </p> 184 184 <button type="button" class="imgpro-btn imgpro-btn-secondary" id="imgpro-manage-subscription"> -
bandwidth-saver/trunk/includes/class-imgpro-cdn-rewriter.php
r3446766 r3447384 16 16 * Transforms image URLs to point to CDN, handles context detection, 17 17 * and processes various WordPress image output hooks. 18 * 19 * Image-only architecture (v1.1+): 20 * - Supports images only (JPG, PNG, GIF, WebP, AVIF, SVG, etc.) 21 * - Video/audio not processed - use Unlimited CDN plugin for media 18 22 * 19 23 * Single-domain architecture (v1.1.0+): … … 194 198 * 195 199 * @since 0.1.0 196 * @since 0.2.0 Added video and audio shortcode filters200 * @since 1.1 Removed video/audio filters - Image CDN only 197 201 * @return void 198 202 */ … … 213 217 add_filter('wp_get_attachment_image_attributes', [$this, 'rewrite_attributes'], 999, 3); 214 218 215 // Content filters (processes img , video, audio, source tags)219 // Content filters (processes img tags only - Image CDN) 216 220 add_filter('the_content', [$this, 'rewrite_content'], 999); 217 221 add_filter('post_thumbnail_html', [$this, 'rewrite_content'], 999); 218 222 add_filter('widget_text', [$this, 'rewrite_content'], 999); 219 220 // Video and audio shortcode filters (WordPress media embeds)221 add_filter('wp_video_shortcode', [$this, 'rewrite_content'], 999);222 add_filter('wp_audio_shortcode', [$this, 'rewrite_content'], 999);223 223 } 224 224 … … 417 417 418 418 /** 419 * Build onerror fallback handler for video/audio elements420 *421 * Creates inline JavaScript that falls back to origin URLs on CDN failure.422 * Uses the same URL conversion pattern as get_onerror_handler() for images.423 * Unlike images, video/audio may have multiple source elements that all424 * need to be rewritten, plus a poster attribute for videos.425 *426 * IMPORTANT: Only transforms URLs that were marked as CDN URLs:427 * - this.src only if data-imgpro-cdn is set on the element428 * - this.poster only if data-imgpro-poster is set on the element429 * - source children only if they have data-imgpro-cdn430 * This prevents corrupting non-CDN URLs (e.g., YouTube embeds).431 *432 * @since 1.0433 * @return string JavaScript onerror handler for media elements.434 */435 private function get_media_onerror_handler() {436 // Fallback logic for video/audio (same pattern as images):437 // 1. Check if not already in fallback state438 // 2. Mark as fallback='1' (trying origin)439 // 3. Track if any URLs were transformed440 // 4. Rewrite direct src ONLY if data-imgpro-cdn is set441 // 5. Rewrite all child source elements with data-imgpro-cdn442 // 6. Rewrite poster ONLY if data-imgpro-poster is set443 // 7. Only call load() if something was transformed (avoid unnecessary retries)444 $handler = "if (!this.dataset.fallback) { "445 . "this.dataset.fallback = '1'; "446 . "var changed = false; "447 // Rewrite direct src only if marked as CDN448 . "if (this.src && this.dataset.imgproCdn) { var p = this.src.split('/').slice(3); this.src = 'https://' + p[0] + '/' + p.slice(1).join('/'); changed = true; } "449 // Rewrite source children (only those with data-imgpro-cdn)450 . "var sources = this.querySelectorAll('source[data-imgpro-cdn]'); "451 . "for (var i = 0; i < sources.length; i++) { var sp = sources[i].src.split('/').slice(3); sources[i].src = 'https://' + sp[0] + '/' + sp.slice(1).join('/'); changed = true; } "452 // Rewrite poster only if marked as CDN453 . "if (this.poster && this.dataset.imgproPoster) { var pp = this.poster.split('/').slice(3); this.poster = 'https://' + pp[0] + '/' + pp.slice(1).join('/'); changed = true; } "454 // Only reload if we actually changed something455 . "if (changed) { this.onerror = function() { this.dataset.fallback = '2'; this.onerror = null; }; this.load(); } "456 . "}";457 458 return $handler;459 }460 461 /**462 419 * Rewrite image attributes 463 420 * … … 515 472 * Rewrite content HTML 516 473 * 517 * Processes mediaelements in HTML content that weren't processed by rewrite_attributes()474 * Processes image elements in HTML content that weren't processed by rewrite_attributes() 518 475 * 519 476 * ARCHITECTURE: … … 523 480 * 524 481 * @since 0.1.0 525 * @since 0.2.0 Added video, audio, and source tag support482 * @since 1.1 Simplified to images only - video/audio not processed 526 483 * @param string $content HTML content. 527 484 * @return string … … 538 495 } 539 496 540 // Early bail-out: Skip processing if no mediatags present497 // Early bail-out: Skip processing if no image tags present 541 498 // This is a performance optimization for text-only content 542 $has_ media_tags = false;543 $tag_patterns = ['<img', '<amp-img', '<amp-anim' , '<video', '<audio', '<source'];499 $has_image_tags = false; 500 $tag_patterns = ['<img', '<amp-img', '<amp-anim']; 544 501 545 502 foreach ($tag_patterns as $pattern) { 546 503 if (false !== stripos($content, $pattern)) { 547 $has_ media_tags = true;504 $has_image_tags = true; 548 505 break; 549 506 } 550 507 } 551 508 552 if (!$has_ media_tags) {509 if (!$has_image_tags) { 553 510 return $content; 554 511 } … … 568 525 * Rewrite content using WP_HTML_Tag_Processor (modern approach) 569 526 * 570 * Processes images, videos, audio, and source elements. 571 * 572 * @since 0.1.0 573 * @since 0.2.0 Added video, audio, and source tag support 527 * Processes image elements only (IMG, AMP-IMG, AMP-ANIM). 528 * Video/audio not processed - use Unlimited CDN plugin for media. 529 * 530 * @since 0.1.0 531 * @since 1.1 Simplified to images only 574 532 * @param string $content HTML content. 575 533 * @return string Modified content. … … 578 536 $processor = new WP_HTML_Tag_Processor($content); 579 537 580 // All tags we process538 // Image tags only - video/audio not processed 581 539 $image_tags = ['IMG', 'AMP-IMG', 'AMP-ANIM']; 582 $media_tags = ['VIDEO', 'AUDIO', 'SOURCE'];583 $all_tags = array_merge($image_tags, $media_tags);584 540 585 541 while ($processor->next_tag()) { 586 542 $tag = $processor->get_tag(); 587 543 588 // Skip if not a mediatag589 if (!in_array($tag, $ all_tags, true)) {544 // Skip if not an image tag 545 if (!in_array($tag, $image_tags, true)) { 590 546 continue; 591 547 } … … 609 565 610 566 // Images: add onload for CSS class and onerror for fallback 611 if (in_array($tag, $image_tags, true)) { 612 $processor->set_attribute('onload', $this->get_onload_handler()); 613 $processor->set_attribute('onerror', $this->get_onerror_handler()); 614 } 615 } 616 } 617 618 // VIDEO/AUDIO: Always add onerror handler for CDN fallback 619 // This is needed even without direct src, because: 620 // - WordPress videos typically use <source> children, not src attribute 621 // - The onerror handler rewrites all child sources with data-imgpro-cdn 622 // - If no CDN sources exist, the handler is a harmless no-op 623 // Note: SOURCE elements don't get onerror - error fires on parent media element 624 if ($tag === 'VIDEO' || $tag === 'AUDIO') { 625 $processor->set_attribute('onerror', $this->get_media_onerror_handler()); 626 } 627 628 // VIDEO tag: also process 'poster' attribute (thumbnail image) 629 if ($tag === 'VIDEO') { 630 $poster = $processor->get_attribute('poster'); 631 if (!empty($poster)) { 632 $origin_poster = $this->get_true_origin($poster); 633 if ($this->should_rewrite($origin_poster)) { 634 $processor->set_attribute('poster', esc_url($this->build_cdn_url($origin_poster))); 635 // Mark poster as CDN so onerror handler knows to transform it 636 $processor->set_attribute('data-imgpro-poster', '1'); 637 } 567 $processor->set_attribute('onload', $this->get_onload_handler()); 568 $processor->set_attribute('onerror', $this->get_onerror_handler()); 638 569 } 639 570 } … … 662 593 * 663 594 * @since 0.1.0 664 * @since 0.2.0 Now supports video, audio, and HLS files595 * @since 1.1 Now supports images only (video/audio removed) 665 596 * @param string $url URL to check. 666 597 * @return bool … … 685 616 } 686 617 687 // Must be a supported media file (images, video, audio, HLS)688 if (!$this->is_ media_url($url)) {618 // Must be a supported image file 619 if (!$this->is_image_url($url)) { 689 620 return false; 690 621 } … … 694 625 695 626 /** 696 * Check if URL is a supported mediafile697 * 698 * Supports images, video, audio, and HLS streaming files.627 * Check if URL is a supported image file 628 * 629 * Supports common image formats only. For video/audio, use Unlimited CDN plugin. 699 630 * 700 631 * @since 0.2.0 632 * @since 1.1 Renamed from is_media_url, removed video/audio 701 633 * @param string $url URL to check. 702 * @return bool True if URL points to a supported mediafile.703 */ 704 private function is_ media_url($url) {634 * @return bool True if URL points to a supported image file. 635 */ 636 private function is_image_url($url) { 705 637 /** 706 * Filter the list of allowed mediaextensions638 * Filter the list of allowed image extensions 707 639 * 708 * @since 1. 0640 * @since 1.1 709 641 * @param array $extensions List of file extensions (without dots) 710 642 */ 711 $extensions = apply_filters('imgpro_ media_extensions', [712 // Images 643 $extensions = apply_filters('imgpro_image_extensions', [ 644 // Images only 713 645 'jpg', 'jpeg', 'png', 'gif', 'webp', 'avif', 'svg', 714 646 'bmp', 'tiff', 'ico', 'heic', 'heif', 715 // Video716 'mp4', 'm4v', 'webm', 'ogv', 'mov', 'mkv',717 // Audio718 'mp3', 'ogg', 'wav', 'm4a', 'flac', 'aac', 'weba',719 // HLS720 'm3u8', 'ts',721 647 ]); 722 648 -
bandwidth-saver/trunk/includes/class-imgpro-cdn-settings.php
r3446766 r3447384 85 85 86 86 /** 87 * Subscription tier: Unlimited (paid, $19.99/mo) 88 * 89 * The main paid tier with unlimited bandwidth and cache. 87 * Subscription tier: Image (paid, $9.99/mo) 88 * 89 * The main paid tier for Image CDN with unlimited bandwidth. 90 * 91 * @since 1.1 92 * @var string 93 */ 94 const TIER_IMAGE = 'image'; 95 96 /** 97 * Subscription tier: Unlimited (legacy, for Unlimited CDN plugin) 98 * 99 * Kept for backward compatibility. New Image CDN users use TIER_IMAGE. 90 100 * 91 101 * @since 0.3.0 … … 200 210 * @var string 201 211 */ 202 const API_BASE_URL = 'https:// cloud.wp.img.pro';212 const API_BASE_URL = 'https://billing.bandwidth-saver.com'; 203 213 204 214 /** … … 402 412 if (isset($settings['cloud_tier'])) { 403 413 $tier = sanitize_text_field($settings['cloud_tier']); 404 if (in_array($tier, [self::TIER_NONE, self::TIER_FREE, self::TIER_ LITE, self::TIER_PRO, self::TIER_BUSINESS, self::TIER_UNLIMITED, self::TIER_ACTIVE, self::TIER_CANCELLED, self::TIER_PAST_DUE, self::TIER_SUSPENDED], true)) {414 if (in_array($tier, [self::TIER_NONE, self::TIER_FREE, self::TIER_IMAGE, self::TIER_LITE, self::TIER_PRO, self::TIER_BUSINESS, self::TIER_UNLIMITED, self::TIER_ACTIVE, self::TIER_CANCELLED, self::TIER_PAST_DUE, self::TIER_SUSPENDED], true)) { 405 415 $validated['cloud_tier'] = $tier; 406 416 } … … 739 749 if (self::MODE_CLOUD === $mode) { 740 750 $tier = $settings['cloud_tier'] ?? ''; 741 // Valid tiers: free (trial), unlimited, lite, pro, business (legacy), active (legacy), past_due (grace period)742 return in_array($tier, [self::TIER_FREE, self::TIER_ UNLIMITED, self::TIER_LITE, self::TIER_PRO, self::TIER_BUSINESS, self::TIER_ACTIVE, self::TIER_PAST_DUE], true);751 // Valid tiers: free (trial), image, unlimited, lite, pro, business (legacy), active (legacy), past_due (grace period) 752 return in_array($tier, [self::TIER_FREE, self::TIER_IMAGE, self::TIER_UNLIMITED, self::TIER_LITE, self::TIER_PRO, self::TIER_BUSINESS, self::TIER_ACTIVE, self::TIER_PAST_DUE], true); 743 753 } elseif (self::MODE_CLOUDFLARE === $mode) { 744 754 return !empty($settings['cdn_url']); … … 785 795 786 796 /** 787 * Check if user has any paid subscription ( unlimitedor legacy tiers)797 * Check if user has any paid subscription (image, unlimited, or legacy tiers) 788 798 * 789 799 * @since 0.1.7 … … 794 804 $tier = $settings['cloud_tier'] ?? ''; 795 805 // past_due still counts as paid (grace period) 796 // unlimited is the primary paid tier, legacy tiers (lite, pro, business) still supported 797 return in_array($tier, [self::TIER_UNLIMITED, self::TIER_LITE, self::TIER_PRO, self::TIER_BUSINESS, self::TIER_ACTIVE, self::TIER_PAST_DUE], true); 806 // image is the primary paid tier for Image CDN, unlimited for Unlimited CDN 807 // legacy tiers (lite, pro, business) still supported 808 return in_array($tier, [self::TIER_IMAGE, self::TIER_UNLIMITED, self::TIER_LITE, self::TIER_PRO, self::TIER_BUSINESS, self::TIER_ACTIVE, self::TIER_PAST_DUE], true); 798 809 } 799 810 … … 848 859 849 860 /** 850 * Check if user is on unlimited tier861 * Check if user is on a tier with unlimited bandwidth (image or unlimited) 851 862 * 852 863 * @since 0.3.0 853 864 * @param array $settings The settings array to check against. 854 * @return bool True if user is on unlimited tier.865 * @return bool True if user is on a tier with unlimited bandwidth. 855 866 */ 856 867 public static function is_unlimited($settings) { 857 return self::TIER_UNLIMITED === ($settings['cloud_tier'] ?? ''); 868 $tier = $settings['cloud_tier'] ?? ''; 869 return in_array($tier, [self::TIER_IMAGE, self::TIER_UNLIMITED], true); 858 870 } 859 871 … … 894 906 $tier = $settings['cloud_tier'] ?? ''; 895 907 switch ($tier) { 908 case self::TIER_IMAGE: 896 909 case self::TIER_UNLIMITED: 897 910 return -1; // Unlimited … … 943 956 $tier = $settings['cloud_tier'] ?? ''; 944 957 switch ($tier) { 958 case self::TIER_IMAGE: 945 959 case self::TIER_UNLIMITED: 946 960 return -1; // Unlimited -
bandwidth-saver/trunk/readme.txt
r3446766 r3447384 1 === Bandwidth Saver: Unlimited MediaCDN ===1 === Bandwidth Saver: Image CDN === 2 2 Contributors: imgpro 3 Tags: media cdn, cdn, video cdn, image cdn, hls streaming3 Tags: image cdn, cdn, image optimization, core web vitals, page speed 4 4 Requires at least: 6.2 5 5 Tested up to: 6.9 6 6 Requires PHP: 7.4 7 Stable tag: 1. 07 Stable tag: 1.1 8 8 License: GPLv2 or later 9 9 License URI: http://www.gnu.org/licenses/gpl-2.0.html 10 10 11 Unlimited media CDN for WordPress. Serve images, video, audio, and HLS streams from 300+ edge servers. $19.99/mo for unlimited bandwidth.11 Image CDN for WordPress. Serve images from 300+ global edge servers. Faster Core Web Vitals, better SEO. $9.99/mo. 12 12 13 13 == Description == 14 14 15 ** Unlimited mediaCDN that makes your WordPress site faster.**16 17 Heavy media files slow down your site. When videos buffer andimages lag, visitors leave, Core Web Vitals fail, and Google ranks you lower.18 19 This media CDN plugin fixes that by serving your images, videos, audio, and HLS streams from 300+ global edge servers. A visitor in Tokyo loads mediafrom Asia. A visitor in London loads from Europe. Everyone gets faster pages.15 **Image CDN that makes your WordPress site faster.** 16 17 Heavy images slow down your site. When images lag, visitors leave, Core Web Vitals fail, and Google ranks you lower. 18 19 This image CDN plugin fixes that by serving your images from 300+ global edge servers. A visitor in Tokyo loads images from Asia. A visitor in London loads from Europe. Everyone gets faster pages. 20 20 21 21 **60-second setup.** No DNS changes. No external accounts. No settings to configure. Just activate and start delivering. 22 22 23 = Why Use a MediaCDN? =24 25 * **Faster page load times** — Media loadsfrom the nearest server instead of traveling across the world from your host23 = Why Use an Image CDN? = 24 25 * **Faster page load times** — Images load from the nearest server instead of traveling across the world from your host 26 26 * **Better Core Web Vitals** — Improve LCP (Largest Contentful Paint) by delivering images faster 27 * **Smooth video playback** — HLS streaming and video files buffer less with edge delivery28 27 * **Higher PageSpeed scores** — Google PageSpeed Insights will show improved performance 29 28 * **Lower bounce rates** — Visitors don't wait for slow sites 30 31 = All Media Types Supported = 32 33 * **Images** — JPG, PNG, GIF, WebP, AVIF, SVG 34 * **Video** — MP4, WebM, MOV with range request support 35 * **Audio** — MP3, WAV, OGG, FLAC 36 * **HLS Streaming** — M3U8 playlists and TS segments 37 38 = How This Media CDN Works = 39 40 1. Install the media CDN plugin from WordPress 29 * **Better SEO** — Speed is a ranking factor 30 31 = All Image Formats Supported = 32 33 * **Standard** — JPG, JPEG, PNG, GIF 34 * **Modern** — WebP, AVIF 35 * **Vector** — SVG 36 * **Other** — BMP, TIFF, ICO, HEIC, HEIF 37 38 = How This Image CDN Works = 39 40 1. Install the image CDN plugin from WordPress 41 41 2. Flip the switch to activate 42 3. Media instantly loadsfrom 300+ global CDN servers42 3. Images instantly load from 300+ global CDN servers 43 43 44 44 That's it. Your original files stay exactly where they are on your server. The plugin only changes URLs on your public pages. Deactivate it and everything returns to normal instantly. 45 45 46 = Unlimited Media CDNPricing =47 48 **Unlimited** ($ 19.99/mo)46 = Pricing = 47 48 **Unlimited** ($9.99/mo) 49 49 * Unlimited bandwidth 50 50 * Custom CDN domain (cdn.yoursite.com) 51 51 * Priority support 52 * Images, video, audio, and HLS streaming52 * All image formats 53 53 54 54 All plans include a 7-day money-back guarantee. … … 56 56 = Self-Hosted Option = 57 57 58 For developers who want full control, you can deploy the open-source worker on your own Cloudflare account. Your media, your infrastructure, zero external dependencies.58 For developers who want full control, you can deploy the open-source worker on your own Cloudflare account. Your images, your infrastructure, zero external dependencies. 59 59 60 60 [Self-hosted CDN setup guide on GitHub](https://github.com/img-pro/bandwidth-saver-worker) … … 62 62 = Works With Any WordPress Theme or Plugin = 63 63 64 This mediaCDN is compatible with:64 This image CDN is compatible with: 65 65 66 66 * **Page builders** — Elementor, Divi, Beaver Builder, Gutenberg, Bricks, Oxygen 67 67 * **WooCommerce** — Product images, galleries, thumbnails 68 * **Video players** — Plyr, VideoJS, native HTML5 video69 68 * **Lazy loading** — Works with native lazy load and plugins 70 69 * **Responsive images** — Full srcset support 71 70 * **Caching plugins** — WP Rocket, LiteSpeed Cache, W3 Total Cache, WP Super Cache 72 73 = Who This Media CDN Is For = 74 75 * Video course creators and membership sites 76 * Podcasters and audio content creators 71 * **Image optimization** — ShortPixel, Imagify, Smush, EWWW 72 73 = Who This Image CDN Is For = 74 77 75 * Bloggers with image-heavy posts 78 * WooCommerce stores with product photos and videos76 * WooCommerce stores with product photos 79 77 * Recipe, travel, and photography sites 80 78 * Portfolio and agency sites 81 * Anyone who wants faster WordPress media loading without complexity 79 * Anyone who wants faster WordPress image loading without complexity 80 81 = Need Video/Audio CDN? = 82 83 This plugin focuses on images for simplicity and cost-effectiveness. If you need video, audio, or HLS streaming support, check out our [Unlimited CDN plugin](https://wordpress.org/plugins/unlimited-cdn/) which supports all media types. 82 84 83 85 == Installation == … … 85 87 **60-second setup. No technical knowledge required.** 86 88 87 1. Install and activate the mediaCDN plugin89 1. Install and activate the image CDN plugin 88 90 2. Go to **Settings > Bandwidth Saver** 89 91 3. Toggle the CDN switch on 90 4. Upgrade to Unlimited for $ 19.99/mo91 92 Done. Your media isnow loading faster from the global CDN.92 4. Upgrade to Unlimited for $9.99/mo 93 94 Done. Your images are now loading faster from the global CDN. 93 95 94 96 == Frequently Asked Questions == 95 97 96 = What media types does this CDN support? = 97 98 The media CDN supports all common media formats: images (JPG, PNG, GIF, WebP, AVIF, SVG), video (MP4, WebM, MOV), audio (MP3, WAV, OGG, FLAC), and HLS streaming (M3U8 playlists and TS segments). 99 100 = Will this media CDN improve my Core Web Vitals? = 101 102 Yes. The media CDN improves LCP (Largest Contentful Paint) by serving media from servers close to your visitors. Faster media delivery means better Core Web Vitals scores. 103 104 = How does video streaming work? = 105 106 The CDN supports HTTP range requests, which means video files can be seeked and streamed without downloading the entire file. HLS streams work seamlessly with M3U8 playlist and TS segment delivery. 98 = What image formats does this CDN support? = 99 100 The image CDN supports all common image formats: JPG, JPEG, PNG, GIF, WebP, AVIF, SVG, BMP, TIFF, ICO, HEIC, and HEIF. 101 102 = Will this image CDN improve my Core Web Vitals? = 103 104 Yes. The image CDN improves LCP (Largest Contentful Paint) by serving images from servers close to your visitors. Faster image delivery means better Core Web Vitals scores. 107 105 108 106 = Does the CDN work with WooCommerce? = 109 107 110 Yes. The media CDN works with WooCommerce product images, galleries, thumbnails, and product videos.108 Yes. The image CDN works with WooCommerce product images, galleries, and thumbnails. 111 109 112 110 = Will this CDN work with my page builder? = 113 111 114 Yes. This mediaCDN works with Elementor, Divi, Beaver Builder, Gutenberg blocks, Bricks, Oxygen, and any other WordPress page builder.112 Yes. This image CDN works with Elementor, Divi, Beaver Builder, Gutenberg blocks, Bricks, Oxygen, and any other WordPress page builder. 115 113 116 114 = Is there a file size limit? = 117 115 118 Files up to 500 MB are supported. This covers most images and many video files. For very large video files, consider dedicated video hosting.116 Files up to 500 MB are supported. This covers all typical image sizes. 119 117 120 118 = Can I use my own domain for CDN URLs? = … … 122 120 Yes. The Unlimited plan supports custom domains (cdn.yoursite.com) with automatic SSL. 123 121 124 = What happens if the mediaCDN goes down? =125 126 Your site automatically serves media directly from your server. Visitors won't notice anything — media just loadsthe normal way until the CDN is back.127 128 = Is this mediaCDN safe? Will it break my site? =129 130 The media CDN cannot break your site. Your original files stay on your server completely untouched. The plugin only changes URLs on your public pages. If the CDN ever has issues, your site automatically falls back to loading mediadirectly. Deactivate the plugin and everything returns to normal instantly.122 = What happens if the image CDN goes down? = 123 124 Your site automatically serves images directly from your server. Visitors won't notice anything — images just load the normal way until the CDN is back. 125 126 = Is this image CDN safe? Will it break my site? = 127 128 The image CDN cannot break your site. Your original files stay on your server completely untouched. The plugin only changes URLs on your public pages. If the CDN ever has issues, your site automatically falls back to loading images directly. Deactivate the plugin and everything returns to normal instantly. 131 129 132 130 = Do I need to change my DNS for this CDN? = 133 131 134 No. Unlike other CDN services, this media CDN works immediately without any DNS changes. Everything happens from your WordPress admin. 132 No. Unlike other CDN services, this image CDN works immediately without any DNS changes. Everything happens from your WordPress admin. 133 134 = Does this support video or audio? = 135 136 No. This plugin focuses on images only for simplicity and cost-effectiveness. If you need video, audio, or HLS streaming support, check out the [Unlimited CDN plugin](https://wordpress.org/plugins/unlimited-cdn/). 135 137 136 138 == Screenshots == 137 139 138 1. Speed up your media in 60 seconds with the unlimited mediaCDN140 1. Speed up your images in 60 seconds with the Image CDN 139 141 2. Track your CDN requests and performance 140 142 3. Multi-site support and custom CDN domains … … 145 147 = What Data Is Collected? = 146 148 147 The mediaCDN plugin does not add cookies, tracking pixels, or analytics to your site.149 The image CDN plugin does not add cookies, tracking pixels, or analytics to your site. 148 150 149 151 = Managed Mode = … … 153 155 * Custom domain settings are sent if configured 154 156 155 Media iscached and served through a global edge network powered by Cloudflare.157 Images are cached and served through a global edge network powered by Cloudflare. 156 158 157 159 = Self-Hosted Mode = 158 160 159 No data is sent to us. Media iscached in your own Cloudflare account.161 No data is sent to us. Images are cached in your own Cloudflare account. 160 162 161 163 == External Services == 162 164 163 This mediaCDN plugin connects to external services:165 This image CDN plugin connects to external services: 164 166 165 167 **Cloudflare (R2 Storage and Workers)** 166 168 167 * Purpose: Mediacaching and global edge CDN delivery169 * Purpose: Image caching and global edge CDN delivery 168 170 * [Terms of Service](https://www.cloudflare.com/terms/) 169 171 * [Privacy Policy](https://www.cloudflare.com/privacypolicy/) … … 180 182 This service is provided on a fair use basis. While we don't impose hard limits, we reserve the right to contact users with exceptionally high usage to discuss dedicated plans or custom arrangements. 181 183 182 The 500 MB per-file size limit applies to all media. For larger files or specialized requirements, please contact us to discuss options.183 184 We aim to provide reliable service for legitimate WordPress mediadelivery. Abuse, excessive automated requests, or use that degrades service for others may result in account review.184 The 500 MB per-file size limit applies to all images. For larger files or specialized requirements, please contact us to discuss options. 185 186 We aim to provide reliable service for legitimate WordPress image delivery. Abuse, excessive automated requests, or use that degrades service for others may result in account review. 185 187 186 188 == Changelog == 189 190 = 1.1 = 191 * Changed: Converted from Media CDN to Image CDN 192 * Removed: Video, audio, and HLS streaming support (use Unlimited CDN plugin instead) 193 * Simplified: Image-only focus for better positioning and simpler codebase 194 * Updated: All UI text and documentation for Image CDN 187 195 188 196 = 1.0 = 189 197 * New: Rebranded as "Bandwidth Saver: Unlimited Media CDN" 190 * New: Simplified pricing - single Unlimited tier at $ 19.99/mo198 * New: Simplified pricing - single Unlimited tier at $9.99/mo 191 199 * New: Video and audio CDN support with range requests 192 200 * New: HLS streaming support (M3U8 and TS segments) … … 206 214 207 215 = 0.2.3 = 208 * Improved: Clearer messaging about mediaCDN speed and Core Web Vitals benefits216 * Improved: Clearer messaging about CDN speed and Core Web Vitals benefits 209 217 * Improved: Simplified onboarding copy 210 218 * Improved: Updated screenshot captions … … 213 221 == Upgrade Notice == 214 222 215 = 1. 0=216 Major update: Now supports video, audio, and HLS streaming. New simplified pricing at $19.99/mo for unlimited bandwidth.223 = 1.1 = 224 Breaking change: Video, audio, and HLS streaming no longer supported. If you use video/audio CDN, install the Unlimited CDN plugin instead before upgrading. 217 225 218 226 == Support ==
Note: See TracChangeset
for help on using the changeset viewer.