How to Create Your Own Website Screenshot Service by Leveraging WordPress’ mShots API Service

Follow me!

If you like this article, go ahead and follow me on Twitter:

Follow @getButterfly

This is an example-based tutorial where you will learn how to create a custom post type called Site, add a URL custom post meta field and generate a screenshot automatically based on that URL (using Automattic’s mShots API service).

The code below uses WordPress.com’s mShots API to generate screenshots on the fly. These images are not stored in your WordPress media library. They are served directly from WordPress.com servers.

As a bonus, we’ll create a shortcode to display everything in a nice loop, and add an option to show or hide the site.

Let’s create our website showcase section!

Custom Post Type

First of all, we create the Site custom post type:

<?php
function shirley_create_sites() {
    $labels = [
        'name'                  => _x('Sites', 'Post Type General Name', 'shirley'),
        'singular_name'         => _x('Site', 'Post Type Singular Name', 'shirley'),
        'menu_name'             => __('Sites', 'shirley'),
        'name_admin_bar'        => __('Site', 'shirley'),
        'archives'              => __('Site Archives', 'shirley'),
        'attributes'            => __('Site Attributes', 'shirley'),
        'parent_item_colon'     => __('Parent Site:', 'shirley'),
        'all_items'             => __('All Sites', 'shirley'),
        'add_new_item'          => __('Add New Site', 'shirley'),
        'add_new'               => __('Add New', 'shirley'),
        'new_item'              => __('New Site', 'shirley'),
        'edit_item'             => __('Edit Site', 'shirley'),
        'update_item'           => __('Update Site', 'shirley'),
        'view_item'             => __('View Site', 'shirley'),
        'view_items'            => __('View Sites', 'shirley'),
        'search_items'          => __('Search Site', 'shirley'),
        'not_found'             => __('Not found', 'shirley'),
        'not_found_in_trash'    => __('Not found in Trash', 'shirley'),
        'featured_image'        => __('Featured Image', 'shirley'),
        'set_featured_image'    => __('Set featured image', 'shirley'),
        'remove_featured_image' => __('Remove featured image', 'shirley'),
        'use_featured_image'    => __('Use as featured image', 'shirley'),
        'insert_into_item'      => __('Insert into site', 'shirley'),
        'uploaded_to_this_item' => __('Uploaded to this site', 'shirley'),
        'items_list'            => __('Sites list', 'shirley'),
        'items_list_navigation' => __('Sites list navigation', 'shirley'),
        'filter_items_list'     => __('Filter sites list', 'shirley'),
    ];

    $args = [
        'label'                 => __('Site', 'shirley'),
        'description'           => __('Site Showcase', 'shirley'),
        'labels'                => $labels,
        'supports'              => ['title', 'thumbnail', 'editor', 'custom-fields'],
        'hierarchical'          => false,
        'public'                => true,
        'show_ui'               => true,
        'show_in_menu'          => true,
        'menu_position'         => 5,
        'menu_icon'             => 'dashicons-format-image',
        'show_in_admin_bar'     => false,
        'show_in_nav_menus'     => false,
        'can_export'            => true,
        'has_archive'           => false,
        'exclude_from_search'   => true,
        'publicly_queryable'    => false,
        'rewrite'               => false,
        'capability_type'       => 'post',
        'show_in_rest'          => true,
    ];

    register_post_type( 'site', $args);
}
add_action('init', 'shirley_create_sites', 0);

Custom Post Meta

Next, we create the custom post meta field:

<?php
/**
 * Add meta box
 *
 * @param post $post The post object
 */
function shirley_add_meta_boxes($post) {
    add_meta_box('site_meta_box', 'Site Settings', 'shirley_build_meta_box', ['site'], 'normal', 'low');
}

/**
 * Build custom field meta box
 *
 * @param post $post The post object
 */
function shirley_build_meta_box($post) {
    wp_nonce_field(basename(__FILE__), 'site_meta_box_nonce');

    $currentSiteUrl = get_post_meta($post->ID, '_site_url', true);
    $currentSiteVisibility = get_post_meta($post->ID, '_site_visibility', true);
    ?>
    <div class="inside">
        <p>
            <label for="site-url">Site URL</label>
            <input type="text" name="site_url" id="site-url" class="regular-text" style="width: 100%;" value="<?php echo $currentSiteUrl; ?>">
        </p>

        <p>
            <label for="site-visibility">Is the site visible in the <b>Showcase</b> section?</label>
            <br>
            <select name="site_visibility" id="site-visibility">
                <option value="0" <?php echo ((int) $currentSiteVisibility === 0) ? 'selected' : ''; ?>>No</option>
                <option value="1" <?php echo ((int) $currentSiteVisibility === 1) ? 'selected' : ''; ?>>Yes</option>
            </select>
        </p>
    </div>
    <?php
}

/**
 * Store custom field meta box data
 *
 * @param int $post_id The post ID.
 */
function shirley_save_meta_box_data($post_id) {
    if (!isset($_POST['site_meta_box_nonce']) || !wp_verify_nonce($_POST['site_meta_box_nonce'], basename(__FILE__))) {
        return;
    }

    if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
        return;
    }
    if (!current_user_can('edit_post', $post_id)) {
        return;
    }

    $siteUrl = isset($_POST['site_url']) ? $_POST['site_url'] : '';
    $siteVisibility = isset($_POST['site_visibility']) ? $_POST['site_visibility'] : '';

    update_post_meta($post_id, '_site_url', $siteUrl);
    update_post_meta($post_id, '_site_visibility', $siteVisibility);
}

add_action('add_meta_boxes', 'shirley_add_meta_boxes');
add_action('save_post', 'shirley_save_meta_box_data');

Showcase Shortcode

And last, we display the sites in a nice list:

<?php
function shirley_sites() {
    $out = '<div class="projects">';

    $args = [
        'post_type' => 'site',
        'posts_per_page' => -1,
        'orderby' => 'menu_order'
    ];

    $the_query = new WP_Query($args);
    if ($the_query->have_posts()) {
        while ($the_query->have_posts()) {
            $the_query->the_post();

            $siteId = get_the_ID();
            $siteVisibility = get_post_meta($siteId, '_site_visibility', true);

            /**
             * mShots
             *
             * Example: https://s.wordpress.com/mshots/v1/https%3A%2F%2F4getbutterfly.com%2F?w=1366
             */
            $siteUri = get_post_meta($siteId, '_site_url', true);
            $siteUri = urlencode($siteUri);
            $siteThumbnail = 'https://s.wordpress.com/mshots/v1/' . $siteUri . '?w=1280&h=960';

            // Override automated post thumbnail with a featured image
            if (has_post_thumbnail($siteId)) {
                $siteThumbnail = get_the_post_thumbnail_url($siteId, 'full');
            }

            if ((int) $siteVisibility !== 0) {
                $out .= '<div class="item" style="background: url(' . $siteThumbnail . ') no-repeat top center; background-size: cover;">
                    <div class="item-info">
                        <h2>' . get_the_title($siteId) . '</h2>
                        <span>
                            <small>' . get_post_meta($siteId, '_site_url', true) . '</small><br>
                            <a href="' . get_post_meta($siteId, '_site_url', true) . '" rel="external" target="_blank">Visit Site</a>
                        </span>
                    </div>
                </div>';
            }
        }
    }

    $out .= '</div>';

    return $out;
}

add_shortcode('sites', 'shirley_sites');

Shortcode Usage

Use the [sites] shortcode to display your sites.

That’s it! Enjoy!

Note that there are no other screenshot options. You can’t change the image quality, image format, the IP address, geolocation, or anything else. Images will be cached for an unspecified period, so you’ll need to mangle the link if you want to regenerate it.

mShots is licensed under GNU General Public License v2.0.

👋 Added by Ciprian on Tuesday, February 9, 2021 in Blog. Last modified on Tuesday, February 9, 2021.

Contribute!

Contribute to this article by sharing your opinion on Twitter:

Unlimited Automated Page Speed Monitoring & Tracking.
Use SpeedFactor to track your website. It’s simple and reliable.
See how real people experience the speed of your website. Then find (and fix) your web performance problems.
Get Started
Privacy Policy