Creating a YouTube API Key for Video Importer

Posted Apr 21, 2015

This tutorial is written for Video Importer, but will work for anyone looking to create an API key for YouTube. The API key is used to identify your project when communicating with YouTube. Google is ending support for their v2 API, so an API key is now needed to run the v3 API.

  1. Create a Project: Visit the Google Developers Console and create a project. Click "Create Project", type in a name, then click "Create". It will take a few seconds for the project to be created, but when it is done you should be take taken to the project's dashboard.
  2. Enable the YouTube API: Open the "APIs and auth" section of the menu on the left then click "APIs". Find the YouTube section and click "YouTube Data API". Now click "Enable API".
  3. Create Credentials: Now that the YouTube API is enabled, click "Credentials" in the left menu. On this page we need to click "Create new Key" under "Public API access". Select "Server key" in the window that pops up, then click "Create". You should now see a long random bit of text which is your new API key.

You're done! Now you can copy and paste this key into Video Importer's settings or wherever you need a YouTube API key.

Introducing Video Importer Pro

Posted Apr 20, 2015

Video Importer is already the best tool for automatically importing videos into your WordPress site, and today we're happy to announce it's getting even better with the release of Video Importer Pro. We've decided to release the full-featured core version of Video Importer for free on the WordPress directory and upgrade all existing license owners to the pro version.

A More Robust Foundation for Everyone

With these changes we'll be able to better optimize performance, track down bugs faster, and explore more new ideas as the number of sites running Video Importer's core version increases.

Faster Release Cycle

We can focus more time on great new pro features as the core version grows more stable. Because the two versions run in tandem together, pro customers will also benefit immediately anytime an update is released for the core version.

Just the Beginning

At launch, the pro version adds the option to set your import schedule anywhere from every 5 minutes to once per day. Other features on the way include custom templates for your imported posts, smart tagging, improved bulk imports, and more.

YouTube API Updates

YouTube integration has been rewritten to support Version 3.0 of the YouTube Data API. This means an API key is now required for YouTube to work. You can set one up for free on the Google Developers Console. If you're running a version of Video Importer lower than 1.6 you need to upgrade or YouTube will stop importing soon.

"No video thumbnail for this post"

Posted Apr 9, 2014

If you're reading this, chances are you're using our Video Thumbnails plugin for WordPress and keep getting the message "No video thumbnail for this post." This can be frustrating, but walking through the steps below can help you fix the issue or at least narrow down the cause so we can help.

  1. Make sure you have saved any changes to your post.
  2. If you are using a a plugin or theme that stores videos in a special meta box other than the main post content editor, be sure you've entered the correct custom field on the settings page. If you don't know the name of the field your video is being saved in, you can try the "Automatically Detect" button in the settings or contact the developer of your video theme/plugin.
  3. Copy and paste your embed code into the "Test Markup for Video" section of the Video Thumbnails Debugging page. If this doesn't find the thumbnail, you'll want to be sure to include the embed code you scanned when you request support. If it does find a thumbnail, please double check that you have the Custom Field set correctly in the settings page if you are using a a plugin or theme that stores videos in a custom field.
  4. Go to the Video Thumbnails Debugging page and click "Download Test Image" to test your server's ability to save an image from a video source. You should see the image appear as well as be able to view it in the media library. Once you've verified that this is working, you can click the "Delete Test Images" button.
  5. Try videos from different sources will help narrow down the problem. If you've only tried with YouTube, try using a video from Vimeo to see if the problem is specific to one site. Be sure to include the sites you've tried when requesting support.
  6. Check the support threads to see if anyone is having the same issue.
  7. If you are still unable to resolve the problem, start a new thread with a good, descriptive title ("Error" or "No thumbnails" is a bad title) and be sure to include the results of your testing as well. Also be sure to include the name of your theme, any video plugins you're using, and any other details you can think of. The more testing and results you can provide, the better the chance of getting the issue resolved quickly!

Note: Comments are disabled on this post. Please use the WordPress support forums for questions regarding the free version and our own support section for issues with the pro version.

Remove Black Bars from YouTube Thumbnails

Posted Apr 9, 2014

Video Thumbnails saves the headache of manually creating and uploading thumbnails to your WordPress site, but sometimes the thumbnails provided by YouTube have annoying black bars on the top and bottom. This is called letterboxing and was common on widescreen videos uploaded before YouTube began supporting HD. Now that we can upload widescreen videos in HD, YouTube provides high-resolution thumbnails at their correct aspect ratio. But for old or standard definition videos, the largest image available from YouTube is a full-screen image that will have letterboxing. Here is an example:

fullscreen

Video Thumbnails will check if a high-definition thumbnail is available and then fall back to the standard definition thumbnail. This means the plugin will sometimes download the letterboxed images created by YouTube. A new feature available in version 1.1 of the pro version solves this problem by adding an option to always crop to a specific aspect ratio. Just select "widescreen" in the settings and new thumbnails will always be cropped to a ratio that will remove those bars. Here is our improved thumbnail:

widescreen

This is just one of the many benefits of upgrading to Video Thumbnails Pro. Existing pro users can upgrade to the latest version by entering their license key on the settings page.

How to Use wp_insert_post tax_input

Posted Mar 3, 2014

The wpinsertpost() function makes it easy to insert a new post into your WordPress database, so we use it in our Video Importer plugin. Constructing a $post array is pretty easy, but a few of the elements can be tricky. Today I'll be teaching you how to use tax_input to save custom taxonomies when inserting a post.

We're going to start with a simple post array. It contains the post's content, title, and a $custom_tax variable that we'll be using to set all of our custom taxonomy data.

$post = array(
    'post_content' => 'This will be the content.',
    'post_title'   => 'Hello World!',
    'tax_input'    => $custom_tax
);

$post_id = wp_insert_post( $post );

Obviously if we try to run this right now, we'll have a problem because we haven't set our $custom_tax data, so let's do that next.

$custom_tax = array(
    'color' => array(
        'Red',
        'Green',
        'Blue'
    )
);

In the example above we're using a non-hierarchical custom taxonomy named "color" and adding Red, Green, and Blue.

Now if we put it all together we get the following:

$custom_tax = array(
    'color' => array(
        'Red',
        'Green',
        'Blue'
    )
);

$post = array(
    'post_content' => 'This will be the content.',
    'post_title'   => 'Hello World!',
    'tax_input'    => $custom_tax
);

$post_id = wp_insert_post( $post );

This should give you a basic understanding of how it works, so next we'll move into some more advanced ways to use tax_input.

Multiple Custom Taxonomies

We can easily use more than one custom taxonomy by expanding our $customtax array to include as many taxonomies as we need. Just create another key with the name of the taxonomy and set the value to an array of items you'd like to add. In the example below we've modified our original $customtax array to include some items for the "size" custom taxonomy.

$custom_tax = array(
    'color' => array(
        'Red',
        'Green',
        'Blue'
    ),
    'size' => array(
        'Small',
        'Medium',
        'Large'
    )
);

Hierarchical vs. Non-Hierarchical Custom Taxonomies

When registering a custom taxonomy in WordPress, it must be either hierarchical or non-hierarchical. Hierarchical taxonomies are like categories, which means items can have parent items and form a tree. This is useful for things like genres (Indie could be a child of Rock), locations (San Francisco could be a child of California), or anything where one group falls into another. Non-hierarchical taxonomies are like tags, where terms are simply saved to a post and don't have parents. This would be used for things like people, teams, or colors.

We've been using non-hierarchical taxonomies so far, so what do we do if we want to use hierarchical ones? Rather than just using the names in tax_input, we need to use the term IDs. In our next example we're going to add some location data to our post using a hierarchical "location" taxonomy with cities belonging to their parent state. If we were to simply use the city and state names, we would end up with a mess of cities and states that wouldn't make much sense. We'd also run into problems when multiple states have cities with the same name. What we need to do is use IDs to make sure cities are saved with their correct state as the parent. Take a quick look then we'll explain what we're doing.

$city = 'Columbus';
$state = 'Ohio';

// Check if the state exists
$state_term = term_exists( $state, 'location', 0 );

// Create state if it doesn't exist
if ( !$state_term ) {
    $state_term = wp_insert_term( $state, 'location', array( 'parent' => 0 ) );
}

// Check if the city exists
$city_term = term_exists( $city, 'location', $state_term['term_taxonomy_id'] );

// Create city if it doesn't exist
if ( !$city_term ) {
    $city_term = wp_insert_term( $city, 'location', array( 'parent' => $state_term['term_taxonomy_id'] ) );
}

$custom_tax = array(
    'location' => array(
        $state_term['term_taxonomy_id'],
        $city_term['term_taxonomy_id']
    )
);

$post = array(
    'post_content' => 'This will be the content.',
    'post_title'   => 'Hello World!',
    'tax_input'    => $custom_tax
);

$post_id = wp_insert_post( $post );

Once we've specified our city and state, we need to check if the state already exists in WordPress. The termexists() function checks if a term already exists and returns the data if it does. By setting the last argument to "0" we're only checking for terms without a parent, which would make sure it is a state. If the state doesn't exist, we're using wpinsert_term() to add it to the WordPress database.

Now that we have the state figured out, we repeat the process for the city with one small change. Instead of using "0" as the parent ID in termexists(), we're going to use the state's ID to make sure we're getting the correct city. If the city hasn't been created for that state, we'll also need to specify the state ID in wpinsert_term().

Now that we know we have the correct city and state data stored as terms, we just need to use their IDs in our $custom_tax array. This method could be expanded to include countries, or applied to something entirely different like genres.

Common Problems & More Info

One common issue is that the user must have the capability to use the specified custom taxonomy. If you're running into problems where this might be the cause, try this solution.

You can check out the wpinsertpost() function reference for more info on constructing a $post array.

How are you using wp_insert_post tax_input?

Let us know how you're using taxinput with wpinsert_post and feel free to leave a comment if you have any questions.

Extending WordPress HTTP Request Timeout Lengths

Posted Feb 21, 2014

The WordPress HTTP API allows developers to easily make HTTP requests across different server configurations, but by default the request times out after 5 seconds. This keeps page load times down on your site if an external request is taking too long, but in some situations you run into errors like "name lookup timed out". Here's how both average users and developers can fix WordPress HTTP request timeouts.

How to Fix "name lookup timed out"

If you're just a normal WordPress users and seeing this error, there's an easy fix. We've written a free plugin that increases the default timeout length from 5 seconds to 30 seconds. This should decrease the chance of running into timeout errors, but you'll still have errors if the URL being requested is having connection issues.

Download our Extend HTTP Request Timeout WordPress Plugin and upload it to your site. Once activated from the plugins panel, you should experience fewer timeouts.

Developer's Guide to HTTP Timeout Errors

If you're a developer you may have stumbled across the "httprequesttimeout" filter. This can be applied site-wide, but it might be wiser to only modify your requests. If you haven't had any timeout issues there's no need to increase the default, but since you're reading this I'll assume you have. If your plugin is making requests that are frequently timing out, you can override the default timeout when using one of the WordPress HTTP API functions like wpremoteget() or wpremotepost(). All you need to do is pass an array of arguments as the second parameter. Here's an example:

wp_remote_get( 'http://example.com/request', array( 'timeout' => 30 ) );

Keep in mind that setting longer timeouts means that users' sites might take longer to load when the URL being requested is slow or having connectivity issues, so look for the right balance between making sure requests have enough time and making sure you aren't waiting 30 seconds for a request that will never load.

Other Resources

Be sure to check out the full documentation on the WordPress HTTP API.

Developers trying to debug issues with their HTTP requests should check out the Core Control plugin. You can enable a log for requests made with the HTTP API which will come in handy for diagnosing intermittent timeouts.

Introducing Video Thumbnails Pro

Posted Feb 11, 2014

When I released the first version of Video Thumbnails over 3 years ago, I wasn't expecting the journey it has taken me on. It was my first plugin, and just a tiny solution for displaying YouTube images on my skateboarding website. Today it grown into an awesome tool that supports 16 providers and saves a lot time for a lot of people every day. The feedback after over 200,000 downloads and hundreds of support threads has taught me an incredible amount and helped it become the robust plugin it is today.

Two weeks ago we released Video Thumbnails Pro, a great tool for professional bloggers and power users. It extends the free version with features like a customizable upload directory and maximum image sizes. You can see a demo in the video below, or check out the full list of features on the plugin's page.

If you love the free version of Video Thumbnails there's no need to worry, because it's not going anywhere. The pro version is installed alongside the free version and hooks into its core, so both free and pro users will benefit from continued updates to the basic version of Video Thumbnails. The main difference is that the free version will maintain a focus on simple automation while the pro version adds additional features and customization options for power users.

We hope you'll continue to enjoy using Video Thumbnails and consider upgrading to Video Thumbnails Pro.

Easily Add Settings to Your Plugin Using a Settings Class

Posted Aug 28, 2013

Ever wanted an easier way to add settings to your WordPress plugin? Whether you're an experienced developer looking to speed up your workflow or a new developer overwhelmed by the Settings API, I'm happy to share a handy bit of code I've written to simplify the process of saving, retrieving, and displaying a settings page.

Including the Class

First, grab a copy of Refactored Settings on GitHub. If you're unfamiliar Git, just choose "Download ZIP" and extract the files. Next you'll need to create a new folder named php/ in your plugin's directory. So if your plugin is in wp-content/plugins/awesome-plugin/, you'll now have wp-content/plugins/awesome-plugin/php/. Now copy the class-refactored-settings.php file we downloaded into this folder.

Now that we have the settings class in place, we can start to incorporate it into our plugin. Don't worry if you're unfamiliar with classes, for now just know that it's a collection of variables and functions.

Open up your plugin's main file and before any of your functions add this line:

require_once( dirname(__FILE__) . '/php/class-refactored-settings.php' );

This will load the code for our settings class. Now we need to open the class-refactored-settings.php file to take a quick look at the class name we'll be using. Near the beginning of the file you'll see a line like this:

class Refactored_Settings_0_2 {

This means the name of our class is RefactoredSettings02. The "02" in this example is a version number for the class, which ensures plugins will be compatible with each other even if they're written using different versions of this class.

Configure the Settings Arguments

Now we need to configure our settings. Open up your main plugin file and after the requireonce() line we added, create an array named $settingsargs. If you want to quickly see how everything works you can copy and paste the one below, or you can scan through it to get an understanding of how to define your settings.

$settings_args = array(

    'file'    => __FILE__, // Plugin file (used to add/remove settings on activation/deactivation)
    'version' => '0.1', // Plugin version
    'name'    => 'Refactored Settings Example Plugin', // The name of the plugin
    'slug'    => 'refactored_settings_example', // The slug to reference and store settings

    // An array of option sections
    'options' => array(

        // An option section array ("general" is the slug for this section)
        'general' => array(
            'name'        => 'General Settings', // The name to display for this settings section
            'description' => 'These settings are general.', // A description to display
            // An array of fields to display in this section
            'fields'      => array(

                // A settings field array
                'color' => array(
                    'name'        => 'Color', // The display name
                    'type'        => 'text', // The type of input
                    'default'     => '', // The default value
                    'description' => 'Your favorite color' // A description
                ),

                // A settings field array
                'milkshake' => array(
                    'name'        => 'Milkshake', // The display name
                    'type'        => 'checkbox', // The type of input
                    'default'     => '1', // The default value
                    'description' => 'Would you like a milkshake with that?' // A description
                )

            )
        ),

        // An option section array ("advanced" is the slug for this section)
        'advanced' => array(
            'name'        => 'Advanced Settings', // The name to display for this settings section
            'description' => 'The settings are advanced.', // A description to display
            // An array of fields to display in this section
            'fields'      => array(

                // A settings field array
                'candy' => array(
                    'name'        => 'Candy', // The display name
                    'type'        => 'dropdown', // The type of input
                    'default'     => 'mms', // The default value
                    // An array of options with values and display names
                    'options'     => array(
                        'gummy-bears' => 'Gummy Bears',
                        'skittles'    => 'Skittles',
                        'mms'         => 'M&Ms'
                    ),
                    'description' => 'Your favorite candy' // A description
                ),

                // A settings field array
                'pizza' => array(
                    'name'        => 'Pizza Toppings', // The display name
                    'type'        => 'multicheckbox', // The type of input
                    // Because multiple checkboxes will have multiple values, the default is an array
                    'default'     => array(
                        'pepperoni'
                    ),
                    // An array of options with values and display names
                    'options'     => array(
                        'extracheese' => 'Extra Cheese',
                        'pepperoni'   => 'Pepperoni',
                        'sausage'     => 'Sausage',
                        'mushroom'    => 'Mushroom'
                    ),
                    'description' => 'Select your favorite pizza toppings' // A description
                ),

                // A settings field array
                'drink' => array(
                    'name'        => 'Drink', // The display name
                    'type'        => 'radio', // The type of input
                    'default'     => 'coke', // The default value
                    // An array of options with values and display names
                    'options'     => array(
                        'coke'      => 'Coke',
                        'dr-pepper' => 'Dr. Pepper',
                        'sprite'    => 'Sprite'
                    ),
                    'description' => 'What would you like to drink?' // A description
                )

            )
        )

    )

);

Create an Instance

Now that we have our settings arguments, it's time to create our Refactored Settings instance. Take the class name we found earlier and add this line:

$my_awesome_settings = new Refactored_Settings_0_2( $settings_args );

Be sure to replace the RefactoredSettings0_2 with whichever version of the settings class you're using. At this point you should be able to see your new settings page in the dashboard, but we haven't incorporated any of the settings into our plugin.

Using the Settings

To use a setting in your plugin, you can use $myawesomesettings like so:

echo $my_awesome_settings->options['general']['color'];

If you're accessing $myawesomesettings from within a function, be sure to include it as a global:

function my_plugin_function() {
    global $my_awesome_settings;
    // Now you can access your settings
    // ...
}

Conclusion

Hopefully you've found this class helpful, let me know if you have any questions. Be sure to watch Refactored Settings on GitHub for updates and feel free to create an issue or submit a pull request!

Automatically Support Video Thumbnails in Your Plugin or Theme

Posted Aug 7, 2013

Actions and Filters are a great feature in the WordPress Plugin API that allow you to override or extend WordPress features. What you may not know is that themes and plugins can also create hooks of their own, allowing plugins and themes to easily work together.

Video Thumbnails takes advantage of filters by allowing developers to alter what content gets scanned for a video thumbnail. If you've ever used a filter before, the process should be pretty straightforward. If you haven't, learning is easy!

Inside Video Thumbnails is this line of code, which allows filters to be added to the markup to be scanned:

$markup = apply_filters( 'video_thumbnail_markup', $markup, $post_id );

So if we have a custom field we want automatically supported by Video Thumbnails, we can use this bit of code in our plugin or theme and 'mycustomfield' will automatically be included in the markup being scanned:

function custom_video_thumbnail_markup( $markup, $post_id ) {
    return get_post_meta( $post_id, 'my_custom_field', true ) . ' ' . $markup;
}

add_filter( 'video_thumbnail_markup', 'custom_video_thumbnail_markup', 10, 2 );

While this post specifically addresses Video Thumbnails, many plugins use their own hooks. Next time you're trying to extend or modify something inside WordPress itself or other plugins, check the code to see if there's a filter or action to tie into.

Creating Custom Shortcode Plugins

Posted Aug 2, 2013

You've probably used shortcodes before, but you might not know that creating a shortcode is pretty easy. You might want to create your own shortcode if you'll be handing off a site to a client who doesn't know HTML, if you want to make something you're constantly using in posts easier, or if theres something in your posts that might need to have its HTML changed in the future.

If you've ever created your own theme or even a simple plugin, you should be able to create your own shortcodes. If you've never written a plugin before and would like to create your shortcode inside a plugin, check out our tutorial on writing your first plugin. It's also possible to create a shortcode within your theme's functions.php file.

Once you have your plugin started or have functions.php open, there's only two things we need to do to create our shortcode. The first thing we'll need is a function that returns the HTML we want to display. In this example we'll be placing an ad in our posts, so let's create a simple function to return the HTML:

function my_ad_shortcode() {
    return '<div class="ad"><!-- This is our ad --></div>';
}

You can replace the HTML with whatever you need to display, just be sure to use return and not echo. Now that we have a function to return our shortcode's HTML, all we need to do is tell WordPress about it.

add_shortcode( 'my_ad', 'my_ad_shortcode' );

This creates the [myad] shortcode and tell WordPress to execute the myad_shortcode() function in its place. One of the great advantages of using a shortcode in this example is that we can control the HTML for all of our ads in one place instead of painfully going through all our posts and updating the code.

Here's our finished product:

<?php

/*
Plugin Name: My Ad Shortcode
Plugin URI: http://refactored.co/blog/creating-custom-shortcode-plugins
Description: A simple shortcode plugin
Author: Refactored Co.
Author URI: http://refactored.co
Version: 0.1
License: GPL2
*/

// Our shortcode function
function my_ad_shortcode() {
    return '<div class="ad"><!-- This is our ad --></div>';
}

// Tell WordPress about it
add_shortcode( 'my_ad', 'my_ad_shortcode' );

?>

There's a lot more you can do with shortcodes, so be sure to check out the Shortcode API docs to learn more.

Capabilities for 'tax_input' using wp_insert_post()

Posted May 14, 2013

Is 'taxinput' not working with wpinsertpost()? If a user doesn't have the capability to work with the custom taxonomy, you'll need to use wpsetobjectterms() after using wpinsertpost(). This can happen when saving user input from the front end because a guest or subscriber won't have permission to work with your custom taxonomy. Check out the wpinsertpost() function reference for more info and be sure to check out the notes.

You can also learn more in our guide to assigning custom taxonomies to a post.

Video Thumbnails 2.0 Released

Posted May 13, 2013

I'm proud to announce that Video Thumbnails 2.0 is available now. You can grab it for free on the WordPress plugin directory or upgrade from your dashboard if you're already using it.

This version has been in the works for longer than I expected, but I learned a great deal in the process. Everything has been rewritten and reorganized from the ground up to make future development easier even as the number of features grows. Support has been added for six new providers, bringing the total to twelve: YouTube, Vimeo, Facebook, Blip, Justin.tv, Dailymotion, Metacafe, Funny or Die, MPORA, Wistia, Youku, and CollegeHumor.

Besides supporting more providers, there are several other new features and improvements:

  • HD YouTube thumbnails (when available)
  • Higher resolution Vimeo thumbnails
  • Private Vimeo videos (must enter an API key in settings)
  • Bulk thumbnail removal
  • Better file names
  • Debugging page for better troubleshooting

If everything already works smoothly for you, hopefully you'll probably never notice the changes. However, there's a good chance you'll benefit from an improved ability to quickly track down bugs and release fixes.

Easily Customize Your WordPress Site Using Widgets

Posted May 10, 2013

Just because you don't know enough code to create your own WordPress theme doesn't mean you can't easily make changes to an existing theme to fit your needs. One of the ways WordPress allows theme authors to include simple customization options is with widgets.

With widgets, customizing certain parts of your site is as easy as dragging and dropping. If your theme supports widgets you'll see a link to "Widgets" under the "Appearance" section of the dashboard. There you'll see which sections the theme developer has enabled widgets for. WordPress includes some built-in widgets and the WordPress extension directory has thousands of plugins offering all kinds of widgets.

Widgets are just one of the many ways WordPress makes managing a website easy for non-developers.

Using WordPress Shortcode Plugins

Posted May 9, 2013

As a blogger there are often times when you want to embed a form, video, or some other bit of HTML. If you aren't familiar with HTML or you simply don't want your post getting cluttered with excessive code, there's a handy feature in WordPress called shortcodes.

Many developers take advantage of the shortcode API to create plugins that let you embed all types of content into your post without the hassle of HTML. A shortcode is a simple tag inside your post that will automatically be replaced with the appropriate HTML when the post is loaded. Shortcodes can look as simple as [contact_form] or have options set inside of them like [product id="3"] or even be wrapped around a piece of information like [video]http://www.youtube.com/watch?v=Im4TO03CuF8[/video].

There are a lot of benefits to using shortcode plugins. Here are just a few:

  1. Less messy HTML in your posts
  2. Easier to learn and mange than HTML
  3. Include dynamic content like weather, tweets, etc.
  4. No need to go back and update old posts when plugins get updated

There are all kinds of shortcode plugins that make creating a great site easier, so don't hesitate to give shortcodes a shot. Before using one for videos, I'd recommend trying oEmbed. Leave a comment with your favorite shortcode plugin and keep an eye out for a tutorial on creating your own shortcodes.

Using a Static Front Page

Posted May 8, 2013

WordPress is great for more than just blogging, so what should you do when a blog isn't the main focus of your website? Setting up a static page with information that's helpful to new visitors is a great idea for many sites. This could be a restaurant's menu, a list of services your business provides, or anything someone stumbling across your site will be interested in.

Simply create a new page (just give it a title like "Home") and put in whatever content you'd like. Next create an empty page, we'll call this one "Blog" and leave the content empty. Now we'll go to Settings → Reading and set "Front page displays" to "A static page." Front page should be set to the page you've created for your homepage, and the posts page will be set to blog. Now whenever someone visits your site's homepage they'll be greeted with static content (ex: refactored.co) and you'll still have a page where your blog is visible (ex: refactored.co/blog).

So if your site doesn't really need a blog to be the main focus, give this a shot.