Sharing on Facebook, AngularJS and the problem with Facebook Scraper

Facebook sends a crawler to every website that is shared on its platform. If the site contains Open Graph (OG) tags then it will construct the shared item according to what is provided. This is why when your share a link it might contain rich data like featured images, descriptions and all sorts of fancy stuff instead of a lonely URL.

This is being an adult

However when your site is a “Single Page Application” and uses a framework like AngularJS then a lot of that data might be created on the clients side. If your site has content specific URLs that are non-genetic then your OG data would ideally need to be updated for each individual URL. It wouldn’t make sense for someone who is sharing a specific image or video from your site to get a generic logo or description as opposed to the shared item.  The problem is that currently setting up your OG meta data through Angular does not work.

Facebook crawlers do not run Javascript when they visits your site. I learned this after I had implemented what I thought was a rather elegant solution of building OG meta tags dynamically through angular. Facebook ignores all of it and returns AngularJS placeholders. (You will get your general {{variable_with_og_data}})

After some research I realized the best solution for PixPit was to recreate the routes on Rails, check to see if the request is from Facebook and redirect accordingly. This would be achieved by checking if the user-agent was coming from Facebook, if so the request would be routed to a specific Rails generated view with the correct OG meta data. otherwise it would send the request to the default view with Angular.

Create a new route that matches the shared URL

  get "/pic/:id" => "application#pic"

The corresponding controller routes the request when a specific picture from PixPit is shared. It would check to see if it’s coming from Facebook, if so it would set up the image/video’s OG meta tag accordingly and redirect to a specific view “fb_pic”, if not then our default index view with Angular is rendered.

  def pic
    agent = request.headers["HTTP_USER_AGENT"].downcase
    
    image = Image.find_by_id(params[:id])
    if agent.include?("facebook")
      @currentUrl = "http://www.pixpit.com/pic/#{params[:id]}/#{params[:stuff]}"
      @currentImage = image.image_url
      @currentTitle = "<meta property=\"og:title\"content= \"#{image.title}\"  />"
      @currentDescription = "<meta property=\"og:description\" content=\"Endless fun!\"/>"
      if image.img_content_type.include?('video/mp4')
        @currentItem = "<meta property=\"og:video\" content=\"#{image.image_url}\"  />"
        @currentItem += "<meta property=\"og:video:width\" content=\"480\" />"
        @currentItem += "<meta property=\"og:video:height\" content=\"270\" />"
        @currentItem += "<meta property=\"og:video:secure_url\" content=\"#{image.image_url.sub("http:/", "https:/")}\"  />"
        @currentItem += "<meta property=\"og:image\" content=\"http://www.pixpit.com/assets/logo-play.png\"  />"
        @currentItem += "<meta property=\"og:video:type\" content=\"video/mp4\"/>"
      else
        @currentItem = "<meta property=\"og:image\" content=\"#{image.image_url}\"  />"
      end
      render "fb_pic"
      return
    end
    render "index"
  end

The “fb_pic” view doesn’t actually have the image or anything else for that matter. The sole purpose of this page is to render the OG meta data for Facebook.

<head>
<%=@currentTitle.html_safe%>
<meta property="og:type" content="movie"/>
<meta property="og:site_name" content="PixPit - Endless fun!"/>
<meta property="og:url"
content= <%=@currentUrl %> />
<%=@currentDescription.html_safe%>
<%=@currentItem.html_safe%>
</head>

As a quick side note, If you want people to be able to play your video directly on Facebook, make sure you set your type to movie. Anything else (video, article, etc..) will not give you an inline player. This is true even if you set up og:video:type.

<meta property="og:type" content="movie"/>

 

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s