About Aaron

Aaron Brazell is an Austin, TX-based entrepreneur at WP Engine, WordPress core contributor and author. He wrote the book WordPress Bible and has been publishing on the web since 2000. You can follow him on Twitter, on his personal blog and view his photography at The Aperture Filter.

TUTORIAL: Using WordPress’Ajax API

WordPress has tons of APIs to do tons of things. It really does. One of the cool ones that I’ve been using a lot lately, has been around for a bit. It’s the Ajax API. Sure, you could write your own Ajaxy thing but why do that when WordPress lets you do it all very simply.

This tutorial will show you how to replicate the functionality that is presented in the “Like” button at Facebook. It assumes that you have WordPress set to require users to be logged in to take such actions. It wouldn’t make much sense for someone to not be logged in for such functionality. Obviously, you could do something else with Ajax (polls? Loading new content?) that doesn’t have the same assumption, but in this case… we’re assuming a user is logged in and the $current_user global is set.

Getting Started

Let’s start with the basic PHP class (you do write good object-oriented code, right?)

1
2
3
4
5
6
7
8
class My_Like_Button {

    function __construct()
    {
    }
}

$my_like_button = new My_Like_Button;

This code is just a basic skeleton that provides a constructor (the __construct() method, which I’ll use later. It also instantiates a new My_Like_Button object and assigns it to the $my_like_button variable for use in the global scope. Obviously, you can use whatever strikes your fancy for the class name or the global variable.

Building the HTML for the Like Button

Next, we need the basic HTML structure that will be used in our theme for the Like button. For the sake of simplicity, I’m not providing any CSS, but feel free to do as you wish. We need to add this as a new method in our class.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function like_button()
{
    if( !is_user_logged_in() )
        return false;
       
    global $current_user;
       
    $html = '<form action="" method="post">
        <input type="hidden" name="like_post_id" id="like_post_id" value="'
. get_the_ID() .'">
        <input type="hidden" name="like_user_id" id="like_user_id" value="'
. $current_user->ID . '">
        <input type="button" name="like_this_post" id="like_this_post" value="Like" />
    </form>'
;
    return $html;
}

This form provides two hidden form fields using get_the_ID() and the $current_user object. Having done this (and after ensuring there is a logged in user), we can now drop this into our theme in the Loop as a template tag:

1
<?php echo $my_like_button->like_button(); ?>

Sending the Ajax Request with jQuery

This is useless by itself. We need something to handle the Ajax. But before we get there, we need to understand how Ajax works within the WordPress context.

All requests must go to wp-admin/admin-ajax.php. Forget the confusion about why you would send a front-end Ajax request to the back-end. You just do.

On the back-end, you’ll have to define functions that will hook into the Ajax API to let WordPress know how to handle the request. More on that in a minute. Let’s build some jQuery to send this to admin-ajax.php.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
function js()
{
    wp_enqueue_script( 'jquery' );
    wp_print_scripts();
    ?>
    <script>
    jQuery(document).ready(function(){
           
        jQuery('#like_this_post').click(function(){
            var like_post_id = jQuery('#like_post_id').val();
            var like_user_id = jQuery('#like_user_id').val();
           
            jQuery.post(
                '<?php echo get_option('siteurl') . '/wp-admin/admin-ajax.php' ?>',
                {
                    action      : 'register_like',
                    user_id     : like_user_id,
                    post_id     : like_post_id,
                    _wpnonce    : '<?php echo wp_create_nonce('nonce-register_like'); ?>',
                },
                function(response) {   
                    alert(response);
                }
            );
               
        });
    });
    </script>
    <?php
}

This is just a PHP function that we can use to throw some jQuery (using the .post() method for our Ajax call) into the head. Note the nonce. You must include this for security. Additionally, you must have an action set. The action is used by WordPress to route the Ajax request.

Finally, we’re passing two extra pieces of data – user_id which is the WordPress user ID and the post_id which is the WordPress post ID of the current $post object inside the Loop. Both of these are supplied in the hidden form fields we created earlier.

Let’s add a new method for hooks and call it in our constructor, so that hooks are executed when the object is instantiated:

1
2
3
4
5
6
7
8
9
function __construct()
{
    $this->hooks();
}
   
function hooks()
{
    add_action( 'wp_head', array( $this, 'js' ) );
}

Supplying the Ajax Handler

Having hooked the jQuery into WordPress, we now need something on the other end to handle the request and return something back to our page. For this, let’s create a method called handle_like().

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function handle_like()
{
    global $wpdb;
    $user_id = (int) $_POST['user_id'];
    $post_id = (int) $_POST['post_id'];
       
    if( !is_user_logged_in() )
        return false;
       
    if( !wp_verify_nonce( $_POST['_wpnonce'], 'nonce-register_like' ) )
        die( 'Go away, asshole!' );
       
    /*
        Here is where we do some sort of database operation to associate
        the Like of the given post with the user who performed the action
       
        Make sure you check for errors. In order to return data, you must
        echo something that the originating page can see. True or false
        only makes sense on this page and not back there.
           
        Typically, you'd output some sort of JSON, XML or plain text.
    */

    $meta_id = add_post_meta( $post_id, 'user_liked', $user_id );
    if( !$meta_id )
        echo "Like not recorded";
    else
        echo "Like recorded";
    exit;
}

In this method, it’s important that all data be sanitized to avoid security problems. I’m performing the most basic of data security here by casting the $_POST variables for the users ID and the post ID to integers.

We’re also checking to make sure the user is logged in. This is why using the built in WordPress Ajax API is actually kind of important. If you build your own Ajax handler, there’s no way to reliable tie in to WordPress to use other APIs like the User API.

Finally, make sure you verify the nonce so you know the request is coming from a legitimate source.

The three security procedures I just listed will largely prevent SQL Injection, ensure authenticated users and eliminate the possibility of Cross Site Request Forgery (CSRF) and generally should be used in all WordPress plugin development.

Simply though, the above method takes the post ID, the user ID and creates a new record in the postmeta table. On success, it will print a success method readable by the original sending page and vica versa on failure.

Note: You must use die() or exit() at the end of the method to make sure the Ajax response exits properly.

Tying the Handler into WordPress

Now that we have a handler method to do our bidding, we need to make sure WordPress knows about it so it routes Ajax requests to the proper place. To do this, we leverage the wp_ajax_{$action} hook.

Remember earlier, while building the jQuery Ajax request, I mentioned that an action POST variable had to be set? WordPress looks to this variable to create a dynamic hook that we can use our new Ajax callback to hook into.

1
add_action( 'wp_ajax_register_like', array( $this, 'handle_like' ) );

Because our action in the js() method was set to register_like, the hook WordPress creates dynamically is wp_ajax_register_like and we can use that to hook our Ajax handler onto.

Wrapping it all Together

Easy right? Use jQuery to send data, wp-admin/admin-ajax.php to receive the Ajax request and pass it on to an appropriate handler function, and send data back to the original page. On the receiving end, you can use normal means to handle the returned data as you wish.

You can download the full code used here at Github.

Blackouts, Boycotts and Regressing From Progress

A couple of weeks ago, the United States, and in fact, the world saw the internet grow up. Namely, through the use of blackouts – a previously unused tactic of protest and grassroots organizing – we saw the evil Stop Online Privacy Act (SOPA) and it’s evil twin Protect IP (PIPA) anti-piracy legislation fail in what seemed like an instant.

Back in December, it became clear that Congress would hearken to their corporate sugar daddys and shove these two pieces of legislation through the Congress without so much as a minimal amount of input from the technology world that would be devastated by their provisions. After votes on these bills were delayed until after the new year, the Internet – led by Wikipedia, Google, Craigslist, and hundreds of thousands of other sites, including this one – self-organized a protest that would involve “blackouts” of sites (and in some cases, very pronounced messaging in he case where blackouts were not feasible.

Despite defensive posturing by the Motion Picture Association of America (MPAA) and others who served to benefit from the legislation, Congressmen and Senators began fleeing the bills en masse. We had successfully made our mark on Washington.

But then a funny thing happened. Twitter made some changes to it’s infrastructure to make it possible for them to operate transparently and legally inside countries that have stricter laws on free speech. It’s a necessary problem that companies have had to face for decades in places like China where speech is censored. I’ll let you read their blog post on the topic.

A small portion of the internet cried foul, claiming censorship. They looked at Twitter as anti-free speech and attempted – unsuccessfully – to self-organize a boycott of Twitter. It failed.

A very specific truth is at play and this is the crux of things. We matured on SOPA blackout day. We decided we wouldn’t be independent and fractioned, which is our nature as independent organizations and people. We had a desired goal (the defeat of SOPA/PIPA) and very specific actions and messaging that needed to happen.

The Twitter boycott (and most boycotts like it) cannot be effective in the same way. The Twitter boycott was a regression in our maturity. We didn’t have the same goal with surgical precision. We didn’t have any ground-swell of support. We had no stated goal or desirable outcome. We can’t use the same tactic every time. We regressed.

And by we, I don’t mean me. I knew it would be a failure.

Grassroots organizing is important and there will be other necessary flexing of muscle. But we can’t just cry foul because we don’t like a decision a company has made. We need to be selective about the fights we engage in and do them tactfully, strategically and surgically. That is maturity.

Congratulations, Internet. We Won the Day.

Today, I feel like a proud poppa. I don’t want to get too celebratory and put out some kind of aura that our battle against SOPA and PIPA are over. In fact, neither are over. But I’ll get to that in a minute, because yesterday was AMAZING!

Yesterday, we saw the Internet come of age. We’ve seen the trend. The Internet has played a crucial role in the Arab Spring, political activism and fundraising as seen in the Obama election campaign in 2008, news reporting as seen in the incident of the US Airways jet in the Hudson River. We’ve seen a definite maturation process on the Internet over the years.

However, we have always been to dysfunctional to be a force. We are all too inbred with independent streaks to band together. In auto racing, cars often “draft” each other to increase speed, because drafting – or riding the sometimes-literal bumper of a car in front of you reduces wind resistence, and increases aerodynamics, thus increasing overall speed of the collective over the individual.

Ladies and gentlemen, we were drafting like pros yesterday.

We were drafting so well that the CEO of the Motion Pictures Association of America (MPAA) – former Senator Chris Dodd – came out shooting at proposed blackouts… on Tuesday before it happened! Mother Jones covers this nicely.

But we went out there, amidst a national media blackout (no pun intended) and did our thing. We were obviously led by the big dogs – WikiPedia, WordPress.com, Google, Tumblr, Reddit and more, but Flickr, WordPress (dot org and dot com), and many more funneled the millions into political action.

This site was blacked out, as were all of my sites. Avatars on Twitter and Facebook were updated en masse with protest messages.

The collective made a statement like we’ve never made a statement before. And it worked. We turned the tide.

13 Senators flipped. Multiple Congressspeople flipped. Sponsors that had names added to the bills, undoubtedly as a matter of normal course of Washington handshakes and blowjobs, suddenly wondered how their names were attached to the bill and suddenly had to reconsider their positions among public scrutiny.

We won the day.

We have not won the battle. To this day, Rep. Lamar Smith, who chairs the House Judiciary Committee, continues to give a middle-finger to his colleagues (including his own Majority Leader) and insists on resuming markup of SOPA in February. Damn the President’s threat to veto. I wrote him a letter yesterday and I wish you would share that across your networks. It’s very important.

Inside the beltway, nothing is dead until it’s dead. Using lines like, “I will not support this bill in its present form” only means, “Go get me some political cover, and I’ll reconsider”. The fact that Eric Cantor says it won’t come to the House floor for a vote, doesn’t mean it won’t. Just because the President says he’s veto it doesn’t mean he will. SOPA needs to be killed in committee and never see the light of day.

Likewise, PIPA in the Senate is losing support very quickly, but if SOPA were to die and PIPA were clear the Senate, my feeling is it would go to the President for a signature and let him make the political call in an election year.

Nothing is dead yet. We must be vigilant. We must maintain the protest, the calls, the emails, the pressure. Stop by your Congressman’s hometown office and talk to his staff. That’ll be more effective than emails and letters and phone calls. Be respectful, but make your voice heard.

Open Letter to Congressman Lamar Smith Regarding SOPA Championing

An email sent to the House Judiciary Committee Chairman, Rep. Lamar Smith (R-TX), who insists on pushing the SOPA bill through committee.

Dear Mr. Smith-

This is an open letter which will be published online, and promoted on Facebook, Twitter and other networks.

As a Texas resident, I find it egregious that you have decided to sell out so uniformly to the entertainment industry. It is so transparent, in fact, that federal records show that your biggest donor are from the holding company for Clear Channel and your biggest campaign contributions come from the entertainment industry itself. Shockingly, the records also show that a Texas elected representative has taken less money from the powerful energy industry that directly effects his constituents, than from an industry who has tried for over a decade to protect their own interests at the expense of your constituents.

This same industry has consistently bullied law-abiding citizens across this country with exorbitant lawsuits and heavy-handed scare tactics.

Your colleagues, in both the House and the Senate, have realized that the Stop Online Piracy Act (SOPA) and the Protect IP Act (PIPA), while idealistic in nature, are destructive to the innovative and stable nature of the Internet – the same nature that has created great economic vitality and growth over the past 20 years.

Your own majority leader, Mr. Eric Cantor, has expressed that SOPA will not come to a vote on the House floor without significant thought, intention, and consensus. This is clearly not happening as your colleagues have backed away from support, going the exact opposite direction from consensus – some even removing their names as co-sponsors.

Sir, you must listen to me and the American public. We see your transparent appeasement to your most significant donors. We understand campaign contributions are important for you and your efforts on behalf of the great State of Texas. However, attempting to ramrod this legislation through will be harmful to Texas, Texas innovation, Texas business as well as collaboration, security and health of the Internet, and business across the nation and globe.

You must abandon your single-sighted focus on ramming this legislation through the House of Representatives with the transparent motive of appeasing your donors. This is a democracy, not a business. You represent us.

Very respectfully,

Aaron Brazell

Your Fiefdom Doesn’t Matter (Or Get your Head out of Your Regional Startup Ass)

Photo used under Creative Commons. Taken by Fellowship of the Rich

There’s this thing called Protectionism. Protectionism is largely a political word used to describe the retreat to self-isolationism for the sake of preserving well-being. It was a word tossed around in late 2008 and 2009 after the market crash when the international community joined together to try to stave off a global economic failure. There were some who believed the United States had their own issues and shouldn’t be worrying about bailing out Europe. This mentality still exists, for better or for worse.

But protectionism is also something that is hurting innovation, business, and startups in an Internet world. It seems like weekly, someone is writing a post about why NYC is the best place to start a company, or why Austin is better than the Valley.

Here’s the honest to God truth… your fiefdoms don’t matter. Your little land grabs and protectionist ideas are hurting the global collective that we all rely on and need. Austin is better than the Valley in some ways but the Valley is better than NYC in others and NYC is better than Europe in others and Europe is better than China in others. You get the point.

Let me pick on my Austin colleagues for a minute. Why don’t you pay attention to what’s happening outside of Austin for a minute? You touted Gowalla as the best thing ever. Why? Because it was from Austin. The data clearly showed differently. Foursquare was better. And now Gowalla is gone and in Palo Alto and doesn’t even exist anymore. Data can’t be argued with.

You think your little community (Austin and other places) makes any real difference? It doesn’t. It’s part of a global community and your little bubble can’t exist in a vacuum. It’s best you start understanding that. We need the Valley. We need Chicago. We need NYC. And they need us.

It’s best we stop pretending that Austin is the best place on earth. It’s not. It’s an awesome place among other awesome places. We are doing awesome things but we aren’t the only people doing awesome things. So let’s stop pretending, get rid of the navel-gazing myopia and get our collective heads out of our asses.

We need our regional fiefdoms for mentorship, collaboration and sharing. We are not the end of the story.

Austin. San Francisco. Europe. New York City. All of us.

Dude, Shut Your Effing Social Media Mouth.

Honey Badger

Honey Badger don't care! (Photo used under Creative Commons. Taken by Bruce McAdam)

It’s been awhile since I ranted. Like really ranted. I’m about to change that.

<rant>

It’s no secret that social media marketing has turned largely douchey. Self-important blowhards show up at SXSW, Blog World Expo and many other industry events every year with the sole purpose of being socialites and schmoozing with their peers and getting into the hottest parties. I’ve done it. We’ve all done it.

But there’s no authenticity in any of it. We call those self-labelled social media gurus as social media douchebags for a reason. It’s because no one (with rare exception) is actually doing real marketing. They are doing friend-mongering. If they can get their clients Facebook likes and Twitter followers then they are being successful. But largely, all they are doing is going to their network of peers who are doing the same goddamn thing and getting them to “Like” their clients Facebook page.

How is this genuine? How is this legitimate? Do I really like Ford because Scott Monty is the head of social media for Ford? Well, I might… and I do like Scott… and I haven’t actually interacted with Scott in a long time so this actually has nothing to do with him.

I added someone who I met in a non-professional setting in Chicago last week to Facebook. I joked with her that it’s surprising we weren’t already friends because we had 41 friends in common.

Why is social media all about clustering together? By all means, we see mutual respect among journalists, but I bet Paul Krugman isn’t tweeting Thomas Friedman asking for a retweet simply to get exposure to his economic op-eds. He doesn’t have to. His work speaks for itself and amplifies itself.

If we dig deep on the social media marketing industry, the discovery under the surface is mind-numbing. I’m about to blow your mind. Social Media people have no clout (or Klout, if you want to play on that metaphor). If they did, their work would self-amplify. They wouldn’t need to look like industry hookers trying to make money with the only assets available to them. They would just… be. And they would be successful. And they wouldn’t have to prove to their clients that they can get the job done. They wouldn’t need to add milestones like “Acquire 1000 Likes on the company Facebook page” or “Build up to 5000 followers on Twitter using mutual retweet tactics” to proposals. Their reputation would precede them. They wouldn’t need to write a book to falsely inflate their value. They would have reputation.

Take Dean McBeth, who I also met last week. Dean works for a small boutique agency in New York. I had never heard of Dean personally, but then he informed me that his claim to fame was architecting the now-legendary Old Spice ads. Ok, your reputation precedes you, then, Dean. Thanks for not asking me to let my network of people know to Like your agency on Facebook.

Look, I understand that there are people like Dean doing great work. For every Dean, however, there are 5 people doing shitty work, relying way to heavily on nerd cred and too little on reputation and results.

People earn their reputations through hard work, perseverence, and time. Yes, that involves networking and schmoozing. But there is no credibility lent to your client by getting a bunch of your friends to “do you a solid” and help you get your work done. If you need 1000 Likes on Facebook, don’t ask me to help unless it’s something that I genuinely like. I’m not going to follow you because you follow me on Twitter. I don’t care about your client… you do. Do good work and let it self-amplify. Otherwise it’s all smoke and mirrors.

</rant>

Update: If you still feel like you need to get a handjob, here’s a list of Social Media conferences where you can meet people, follow them on Twitter for the purpose of using your network for the benefit of your client later down the road.