WP Manifestindependent plugin directory
manifest / privacy / clear-embed

ClearEmbed

A WordPress plugin that replaces third-party embeds with lightweight, privacy-respecting versions rendered from local metadata and templates.

★ 0stars

Install

Download source zip No release zip yet

This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.

Install straight from GitHub with WP-CLI:

wp plugin install https://github.com/donohoe/clear-embed/archive/refs/heads/main.zip
No built-in updater. New versions won't appear under Dashboard → Updates. Install new releases yourself, or let Git Updater track the repository.

A WordPress plugin that replaces third-party embeds with lightweight, privacy-respecting versions rendered from local metadata and templates. ClearEmbed caches content locally and provides click-to-activate embed loading for improved privacy and performance.

⚠️ Development Status

ClearEmbed is still in active development. While the core functionality is working, you may encounter bugs or incomplete features. Use with caution in production environments and report any issues you find.

Features

  • Privacy-First: Click-to-load embeds reduce tracking and improve privacy
  • Performance: Lightweight local templates instead of heavy third-party scripts
  • Offline-Ready: Stores embed data locally for better reliability
  • Image Optimization: Automatically creates mobile-optimized versions of images
  • Profile Image Caching: Downloads and caches creator/channel avatars locally
  • Deleted Content Tracking: Monitors embed availability and preserves deleted content
  • Extensible: Service-based architecture for easy addition of new platforms
  • Cache-Friendly: All embed data stored on filesystem, not database
  • Admin Interface: Settings panel with service management and maintenance tools

Supported Services

  • ✅ YouTube - Videos with thumbnails, channel avatars, and metadata
  • ✅ Twitter/X - Tweets with OpenGraph cards, media detection, and profile images
  • ✅ Spotify - Tracks, albums, episodes, shows with artwork and custom audio player
  • ✅ TikTok - Videos with thumbnails and creator avatars
  • ✅ Bluesky - Posts with media grids, video support, and profile images
  • 🔲 SoundCloud
  • 🔲 SnapChat
  • 🔲 Vimeo

Installation

  1. Upload the plugin files to /wp-content/plugins/embeds/
  2. Activate the plugin through the WordPress admin
  3. Configure settings at Settings > Embeds
  4. Enable desired services in the settings panel

Directory Structure

/wp-content/embeds/
├── youtube/
│   └── {video_id}/
│       ├── data.json
│       ├── image.jpg
│       ├── image-mobile.jpg
│       └── avatar.jpg
├── twitter/
│   └── {tweet_id}/
│       ├── data.json
│       ├── card.jpg
│       ├── card-mobile.jpg
│       └── avatar.jpg
├── spotify/
│   └── {track_id}/
│       ├── data.json
│       ├── image.jpg
│       ├── image-mobile.jpg
│       └── avatar.jpg
├── tiktok/
│   └── {video_id}/
│       ├── data.json
│       ├── image.jpg
│       ├── image-mobile.jpg
│       └── avatar.jpg
├── bluesky/
│   └── {post_id}/
│       ├── data.json
│       ├── image-1.jpg
│       ├── image-1-mobile.jpg
│       ├── card.jpg
│       ├── card-mobile.jpg
│       └── avatar.jpg
└── .htaccess

Service Features

YouTube

  • Data Source: oEmbed API + channel page scraping
  • Content: Video metadata, thumbnails, channel information
  • Images: Video thumbnails (multiple quality fallbacks), channel avatars
  • Features: Click-to-play with iframe loading, channel links

Twitter/X

  • Data Source: oEmbed API + HTML parsing
  • Content: Tweet text, author info, OpenGraph cards
  • Images: Card images, profile avatars, media detection
  • Features: Card previews, media indicators, engagement metrics

Spotify

  • Data Source: oEmbed API + NextJS data extraction
  • Content: Track/episode metadata, artwork, preview audio
  • Images: Album/show artwork, artist avatars (tracks only)
  • Features: Custom audio player, dynamic theming, duration display

TikTok

  • Data Source: oEmbed API + page scraping
  • Content: Video metadata, creator info, engagement stats
  • Images: Video thumbnails, creator avatars
  • Features: Engagement metrics, click-to-play interface

Bluesky

  • Data Source: AT Protocol API
  • Content: Post text, author info, media, external links
  • Images: Post images (1-4 grid), card images, profile avatars
  • Features: Media grids, video support, external link cards

Privacy & Performance Features

Click-to-Activate

All embeds load as static previews initially, only loading third-party content when clicked by the user.

Local Image Caching

  • Thumbnails: Cached locally with mobile-optimized versions
  • Profile Images: Creator/channel avatars cached for all services
  • Responsive: Automatic mobile versions for bandwidth optimization
  • Privacy: No external image requests on page load

Deleted Content Tracking

  • Availability Monitoring: Periodic checks for deleted/private content
  • Lazy Checking: Checks performed only when content is accessed
  • Preservation: Option to preserve deleted embed data
  • Admin Tools: Bulk maintenance and selective deletion

Admin Interface

Settings Panel (Settings > ClearEmbed)

  • Service Management: Enable/disable individual services
  • Discovered Services: Auto-detection of available service handlers
  • Maintenance Tools: Clear embed data with preservation options
  • Statistics: Embed counts and storage usage

Service Discovery

The plugin automatically discovers service handlers in the /services/ directory and provides admin controls for enabling/disabling them.

Extensibility

Adding Custom Services

  1. Create service directory: /services/my-service/
  2. Add handler class: /services/my-service/handler.php
  3. Add template: /services/my-service/template.php
<?php
class ClearEmbed_MyService_Handler extends ClearEmbed_Service_Handler {
    protected $service_name = 'my-service';

    public function can_handle($url) {
        return strpos($url, 'example.com') !== false;
    }

    public function extract_embed_id($url) {
        // Extract unique ID from URL
    }

    public function fetch_embed_data($url, $embed_id) {
        // Fetch and return embed data array
    }

    public function get_template_data($embed_data) {
        // Transform data for template use
    }

    public function check_embed_availability($url, $embed_id) {
        // Check if content still exists
    }

    public function get_supported_patterns() {
        return array('example.com/*');
    }
}

Template Structure

Templates receive processed data and should handle responsive display:

<?php if (!defined('ABSPATH')) exit; ?>

<div class="clearembed-myservice" data-id="<?php echo esc_attr($id); ?>">
    <!-- Static preview content -->
    <div class="clearembed-myservice-placeholder" onclick="loadEmbed()">
        <!-- Preview with local images -->
    </div>

    <!-- Hidden iframe for click-to-load -->
    <iframe data-src="<?php echo esc_url($embed_url); ?>" style="display:none;"></iframe>
</div>

WordPress Filters

ClearEmbed provides extensive filter hooks for customization:

Core Processing Filters

clearembed_processable_url

Parameters: $should_process, $url
Description: Control whether a URL should be processed by ClearEmbed

add_filter('clearembed_processable_url', function($should_process, $url) {
    // Skip processing for specific domains
    if (strpos($url, 'internal.example.com') !== false) {
        return false;
    }
    return $should_process;
}, 10, 2);

clearembed_embed_html

Parameters: $html, $service, $embed_data
Description: Modify final embed HTML output

add_filter('clearembed_embed_html', function($html, $service, $embed_data) {
    // Add custom wrapper for YouTube embeds
    if ($service === 'youtube') {
        return '<div class="custom-youtube-wrapper">' . $html . '</div>';
    }
    return $html;
}, 10, 3);

clearembed_fallback_content

Parameters: $fallback, $url, $service
Description: Provide custom fallback content when embed processing fails

add_filter('clearembed_fallback_content', function($fallback, $url, $service) {
    return '<p>Content from ' . $service . ' is temporarily unavailable.</p>';
}, 10, 3);

Service Management Filters

clearembed_enabled_services

Parameters: $enabled_services
Description: Programmatically control which services are enabled

add_filter('clearembed_enabled_services', function($services) {
    // Disable TikTok on production
    if (WP_ENV === 'production') {
        $services = array_diff($services, ['tiktok']);
    }
    return $services;
});

clearembed_supported_services

Parameters: $services
Description: Filter the list of supported services

Data Processing Filters

clearembed_embed_data

Parameters: $embed_data, $service, $url
Description: Modify embed data before storage

add_filter('clearembed_embed_data', function($data, $service, $url) {
    // Add custom metadata
    $data['processed_at'] = current_time('c');
    $data['source_domain'] = parse_url($url, PHP_URL_HOST);
    return $data;
}, 10, 3);

clearembed_template_data

Parameters: $template_data, $embed_data, $service
Description: Modify data passed to templates

add_filter('clearembed_template_data', function($template_data, $embed_data, $service) {
    // Add custom CSS classes
    $template_data['custom_class'] = 'my-theme-embed';
    return $template_data;
}, 10, 3);

Image Processing Filters

clearembed_skip_image_download

Parameters: $skip, $url, $service, $image_type
Description: Skip image downloads conditionally

add_filter('clearembed_skip_image_download', function($skip, $url, $service, $type) {
    // Skip avatar downloads for YouTube
    if ($service === 'youtube' && $type === 'avatar') {
        return true;
    }
    return $skip;
}, 10, 4);

clearembed_image_quality

Parameters: $quality, $service, $image_type
Description: Control JPEG compression quality

add_filter('clearembed_image_quality', function($quality, $service, $type) {
    // Higher quality for thumbnails
    if ($type === 'thumbnail') {
        return 95;
    }
    return $quality;
}, 10, 3);

API Request Filters

clearembed_api_request_args

Parameters: $args, $service, $request_type
Description: Modify API request arguments

add_filter('clearembed_api_request_args', function($args, $service, $type) {
    // Add custom headers for Spotify
    if ($service === 'spotify') {
        $args['headers']['X-Custom-Header'] = 'MyApp/1.0';
    }
    return $args;
}, 10, 3);

Content Sanitization Filters

clearembed_sanitize_content

Parameters: $content, $content_type, $service
Description: Sanitize content before display

add_filter('clearembed_sanitize_content', function($content, $type, $service) {
    // Custom sanitization for Twitter text
    if ($service === 'twitter' && $type === 'text') {
        return wp_kses_post($content);
    }
    return $content;
}, 10, 3);

Template System Filters

clearembed_template_path

Parameters: $template_path, $service
Description: Override template file paths

add_filter('clearembed_template_path', function($path, $service) {
    // Use theme template if available
    $theme_template = get_template_directory() . '/clearembed/' . $service . '.php';
    if (file_exists($theme_template)) {
        return $theme_template;
    }
    return $path;
}, 10, 2);

clearembed_css_classes

Parameters: $classes, $service, $context
Description: Modify CSS classes in templates

add_filter('clearembed_css_classes', function($classes, $service, $context) {
    // Add dark mode class
    if (get_theme_mod('dark_mode_enabled')) {
        $classes[] = 'dark-mode';
    }
    return $classes;
}, 10, 3);

Service-Specific Filters

clearembed_embed_url_params

Parameters: $params, $service, $embed_id
Description: Modify iframe embed URL parameters

add_filter('clearembed_embed_url_params', function($params, $service, $id) {
    // Disable YouTube related videos
    if ($service === 'youtube') {
        $params['rel'] = '0';
        $params['modestbranding'] = '1';
    }
    return $params;
}, 10, 3);

Configuration Filters

clearembed_availability_check_days

Parameters: $days
Description: Control how often embed availability is checked

add_filter('clearembed_availability_check_days', function($days) {
    return 14; // Check every 2 weeks instead of 7 days
});

Usage Examples

Custom YouTube Embed Parameters

// Disable related videos and enable modest branding
add_filter('clearembed_embed_url_params', function($params, $service, $id) {
    if ($service === 'youtube') {
        $params['rel'] = '0';
        $params['modestbranding'] = '1';
        $params['color'] = 'white';
    }
    return $params;
}, 10, 3);

Skip Processing for Internal URLs

// Don't process embeds from internal staging sites
add_filter('clearembed_processable_url', function($should_process, $url) {
    $internal_domains = ['staging.example.com', 'dev.example.com'];
    $domain = parse_url($url, PHP_URL_HOST);

    if (in_array($domain, $internal_domains)) {
        return false;
    }
    return $should_process;
}, 10, 2);

Custom Error Handling

// Provide branded fallback content
add_filter('clearembed_fallback_content', function($fallback, $url, $service) {
    $service_name = ucfirst($service);
    return sprintf(
        '<div class="embed-error"><p>%s content is currently unavailable. <a href="%s" target="_blank">View on %s</a></p></div>',
        $service_name,
        esc_url($url),
        $service_name
    );
}, 10, 3);

Available Hooks

  • Service Registration: Automatic discovery from /services/ directory
  • Template Override: Place custom templates in theme directory
  • Data Processing: Filter embed data before storage/display
  • Image Processing: Customize image optimization settings

Requirements

  • WordPress 5.0+
  • PHP 7.4+
  • Writable /wp-content/embeds/ directory
  • GD extension (for image processing)
  • cURL/WordPress HTTP API (for remote requests)

Privacy Forward

  • No Third-Party Requests: Content loads only when user explicitly clicks
  • Local Storage: All data cached locally, no external dependencies
  • GDPR Friendly: Reduces tracking and data collection from embed providers
  • User Control: Click-to-activate gives users choice over loading external content

Performance Benefits

  • Reduced Page Weight: Local templates much lighter than third-party widgets
  • Faster Loading: No blocking requests to external services
  • Mobile Optimized: Responsive images reduce bandwidth usage
  • Caching: Filesystem storage eliminates database overhead

License

GPL v2 or later