Build Your Own Spotify Widget for WordPress

Music Widget

The WordPress admin widget appearance page. Our “Music List” widget customization options appear on the right side.

I listen to a lot of music while I work. It is an integral part of my process. Typically, I listen on Spotify. Spotify allows me to share what I’m listening to on my Facebook wall, but I prefer to share what I’m listening to on my own site. I also want to control the display of this information. Since widgets are typically goofy, branded, and ugly, I built my own. I’ve updated it a few times, but I have been using it on my site for a number of years now. Here’s how you can build your own Spotify Widget for WordPress.

Requirements:

  1. You’ll need a Last.fm account.
  2. You’ll need a Last.fm API key.

I mentioned Spotify above, but Last.fm does all the real work here. Please note that you can listen to music and push your tracks to your site with Last.fm alone, but I’ve found Spotify’s selection and ease-of-use preferable.

Optional:

  1. A Spotify account. Once you sign up for both Last.fm and Spotify, you’ll need to turn on scrobbling to Last.fm within Spotify’s preferences. You will need your Last.fm username and password.
  2. Download the Last.fm Scrobbler to push your recently listened tracks to your this widget via iTunes as well! There’s a Windows version as well.

Onward

Alright, let’s get down to business — we’re building a WordPress widget that will live inside your theme. I will not get very deep into how to create widgets for WordPress — feel free to check out WordPress.org for more information. I will instead focus on how we acquire and output the data we request from Last.fm.

If you have a short attention span, a copy/paste of the code on GitHub into your theme’s functions.php and style.css files will have you rolling in no time.


<?php
class SH_Music extends WP_Widget { 
    public function __construct() { 
        $widget_ops = array( 'classname' => 'Music List', 'description' => 'Displays a list of recenty played music from Last.fm or Spotify.' ); 
        $this->WP_Widget( 'SH_Music', 'Music List', $widget_ops ); 
}

We fire it up with our “SH_Music” class, and build our widget — it is named “Music List” and will appear on the Appearance > Widgets page in the admin. Depending on your theme, you will be able to display the widget in the footer or the sidebar.


function widget( $args, $instance ) {
    extract( $args, EXTR_SKIP );
    $title = empty( $instance['widget_title'] ) ? 'Listening to This' : apply_filters( 'widget_title', $instance['widget_title'] );
    $amount = empty( $instance['display_amount'] ) ? '3' : apply_filters( 'display_amount', $instance['display_amount'] );
    $latest = '';
    $error = 'I\'m not listening to anything at the moment, unfortunately.';
    echo ( isset( $before_widget ) ? $before_widget: '' );
    if ( !empty( $title ) )
	    echo $before_title . $title . $after_title; ?>

The widget function is where most of the magic happens — it determines the output on the front end, so I’ll break it up into sections. We set up the $title, $amount, and $latest variables first, and output the widget $title. We provide a default value, “Listening to This,” in case the widget_title option was not set in the WordPress admin. We also provide a default value of “3” for $amount — this is the number of recently listened tracks the widget will display. $latest is left empty for now, but will hold an array of our tracks from Last.fm. $error contains a message to display on the front end if something has gone wrong.


<ul class="media-list">
    <?php if ( empty( $instance['lastfm_username'] ) || empty( $instance['lastfm_api_key'] ) ) : ?>
        <li class="media">
            <p>Please enter your <a href="http://www.last.fm/" target="_blank">Last.fm</a> credentials to use this widget.</p>
        </li>
        <?php else :
            $username = apply_filters( 'lastfm_username', $instance['lastfm_username'] );
            $api_key = apply_filters( 'lastfm_api_key', $instance['lastfm_api_key'] );
            $latest = get_transient( 'mylastfmtracks_' . $username );
            if ( false == ( $latest ) ) {
                $request_url = 'http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=' . $username . '&limit=' . $amount . '&api_key=' . $api_key . '&format=json';
                $ch = curl_init();
                curl_setopt( $ch, CURLOPT_URL, $request_url );
                curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
                curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, 20 );
                $tracks = curl_exec( $ch );
                $latest = ( curl_error( $ch ) ) ? 'broken' : $tracks;
                curl_close( $ch );
                set_transient( 'mylastfmtracks' . $username, $latest, 60 ); 
	  }
	  <?php

We begin our list output by checking if the Last.fm username and API key options were populated on the back end. If either value is missing, a message will display on the front end to notify users that these credentials are required. If the values are present, we build a request loop:

  1. We set a transient containing the return JSON of our Last.fm request (our recently listened tracks), and set its lifespan to 60 seconds.
  2. We retrieve the transient, and set $latest to the transient value.
  3. If the transient has expired, we request our tracks from Last.fm again, and reset $latest.
  4. If the request returns an error, Last.fm is probably down, so we set $latest to “broken.”

if ( $latest == 'broken' ) : ?>
    <li class="media">
        <p class="tight"><?php echo $error; ?></p>
    </li>

If $latest is set to broken, we output the $error message set above.


<?php
else :
    $latest = json_decode( $latest, true );
    if ( $latest['recenttracks']['track'] ) :
        $i = 0;
        foreach ( $latest['recenttracks']['track'] as $track ) :
            // setup variables
            $artist = ( isset( $track['artist']['#text'] ) ) ? $track['artist']['#text'] : ''; // artist name
            $title = ( isset( $track['name'] ) ) ? $track['name'] : ''; // track title
            $track_url = ( isset( $track['url'] ) ) ? $track['url'] : ''; // track url on Last.fm
            $albumArt = ( isset( $track['image'][1]['#text'] ) ) ? $track['image'][1]['#text'] : ''; // medium-sized album art
            $nowPlaying = ( isset( $track['@attr']['nowplaying'] ) ) ? true : ''; // true if track is currently playing
            $datePlayed = ( isset( $track['date']['uts'] ) ) ? $track['date']['uts'] : ''; // time played
            date_default_timezone_set("America/New_York"); // set your timezone here
            ?>

We decode the JSON data we retrieved from Last.fm, converting the JSON to a PHP array. We then run a test to determine if the data contains our tracks. If $latest contains our tracks, we loop through each track and setup our values (all commented above). We also set up a counter ($i = 0) that we will use output the correct number of songs (specified in $amount). Please note that I’ve set the default timezone to “America/New_York” — you will need to set this to your own timezone.


<li class="media">
    <div class="pull-left">
        <?php if ( $albumArt != '' ) : // Test if there's album art. If not, use default ?>
            <img class="media-object" src="<?php echo esc_attr( $albumArt ); ?>"  width="64px" height="64px" alt="Album Art for <?php echo esc_attr( $title ); ?>" />
        <?php else : ?>
            <div class="media-object no-album-art" title="No Album Art Available">
                <span class="now-playing"><i class="icon-type-music"></i></span>
            </div>
        <?php endif; ?>
    </div>

Now we begin creating the <li> item. The first <div> (pull-left) inside the list item contains the album art. If the album art doesn’t exist, we use a placeholder. In this case, we include an infinity sign that slowly blinks via css. On my site, I use a music note icon. You can customize this placeholder as you like.


    <div class="media-body">
        <h5 class="media-heading"><?php echo $artist; ?></h5>
        <small>
            <p class="tight"><a href="<?php echo $track_url; ?>"><?php echo $title; ?></a><br />
                <?php if ( $nowPlaying == true ) : // Test if song is playing right now. ?>
                    <span class="text-muted">Listening now</span>
                <?php else : ?>
                    <span class="text-muted"><?php echo human_time_diff( $datePlayed ); ?> ago</span>
                <?php endif; ?>
            </p>
        </small>
    </div>
<?php $i++; ?>
</li>
<?php if ( $i == $amount ) { break; }
endforeach;
else : ?>

The second half of the <li> item (media-body) contains the artist name, the song title, and the time the song was played. If the song is currently playing, “Listening now” is output, the time difference between now and when the song was played (<time diff> ago) is displayed. When the counter equals $amount, we stop outputting <li> items.


    <li class="media">
        <p class="tight"><?php echo $error; ?></p>
    </li>
    <?php endif; ?>
<?php endif; ?>
<?php endif; ?>
</ul>
<?php echo ( isset( $after_widget ) ? $after_widget: '' );
}

We include one final fallback. If the XML is not formatted as expected or if it is missing the tracks, we output the $error message. That’s it — The list is done! This concludes the front end output.


public function form( $instance ) {
    $instance = wp_parse_args( ( array ) $instance, array( 'widget_title' => '', 'lastfm_username' => '', 'lastfm_api_key' => '', 'display_amount' => '' ) );
    $title = $instance['widget_title'];
    $username = $instance['lastfm_username'];
    $api_key = $instance['lastfm_api_key'];
    $amount = $instance['display_amount'];
    ?>
    <p>
        <label for="<?php echo $this->get_field_id( 'widget_title' ); ?>">Title: 
            <input class="widefat" id="<?php echo $this->get_field_id( 'widget_title' ); ?>" name="<?php echo $this->get_field_name( 'widget_title' ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>" />
        </label>
    </p>
    <p>
/** – – Abridged for brevity. Full code is on Github. – – **/

The rest of the SH_Music class builds and updates the widget options in the WordPress admin. This code is pretty straightforward. We create four fields in the “form” function, and update the options in the “update” function. The four options include:

  1. widget_title – the title that appears at the top of the music list on the front end. Defaults to “Listening to This.”
  2. lastfm_username – the Last.fm user name used in the API request. No default.
  3. lastfm_api_key – the Last.fm API key used in the API request. No default.
  4. display_amount – the number of songs to display in the widget (up to 5). Defaults to 3.

There you have it — a music list widget that you can style to match your site! The code on Github is yours to use as you see fit. No credit is necessary. Happy trails!

Categories: Tutorial