GithubHelp home page GithubHelp logo

hhy5277 / angular-social-demo Goto Github PK

View Code? Open in Web Editor NEW

This project forked from michaelbromley/angular-social-demo

0.0 1.0 0.0 1.51 MB

A demo of how to allow social media crawlers (Facebook, Twitter, Pinterest etc) to read your AngularJS app

HTML 39.22% JavaScript 28.05% PHP 32.73%

angular-social-demo's Introduction

AngularJS Social Demo

This is a project which aims to illustrate how to enable rich social media sharing of your AngularJS app. This was created to accompany a talk on the same subject I am giving at the Vienna AngularJS meetup on 30th June 2014

A working demo of the following implementation can be found here, and all the code is contained in this repo.

Background

When sharing a link on social media website such as Facebook and Twitter, the site will send a crawler to the URL being shared in order to scrape data from it to make the link richer. The data scraped typically includes a title, description, image, and potentially much more. A common way to convey this information is via the Open Graph Protocol (used by Facebook, Pinterest, Google+). Briefly, to use it one would include special meta tags in the header of your HTML document:

<head>
    <meta property="og:title" content="My Page" />
    <meta property="og:description" content="A description of my page." />
    <meta property="og:image" content="http://www.mysite.com/images/my_lovely_face.jpg" />
    <!-- etc. -->
</head>

These meta tags are then read by the crawler and the contents are used to generate a richer sharing model (e.g. by including the image and description in the Facebook timeline)

The problem with AngularJS apps is that the entire view is built by JavaScript on the client, but (as of this writing at least), the various social media crawlers do not execute JavaScript on the target URL, and as a result they will only see the raw HTML template without any content. To the crawler, your template would look something like this:

<head>
    <meta property="og:title" content="{{ page.title }}" />
    <meta property="og:description" content="{{ page.description }}" />
    <meta property="og:image" content="{{ page.image }}" />
    <!-- etc. -->
</head>

Solution

The solution is basically to use some kind of server-side user-agent detection to pick up whenever a social media crawler arrives, and then instead of showing it the plain AngularJS template file, redirect it to a server-generated page that will contain the desired meta tags, all filled with the correct information.

What we will need

  1. A web server capable of URL rewriting. In this case, we are using Apache and the mod_rewrite module.
  2. A server-side language to generate our crawler-friendly pages. In this case I will use PHP.
  3. The Angular app must be using "html5mode" its URLs. This is because the # portion of a URL does not get sent to the server, so makes server-side redirection based on the Angular page impossible. For more information, see this StackOverflow answer.

Following is a write-up of how to set things up assuming the above technologies are being used.

Configure Apache

We will need three specific Apache modules enabled: mod_rewrite, mod_proxy and mod_proxy_http (installation of these modules will vary depending on your OS/Apache version, but is beyond the scope of this article). We will come back to the use of these modules shortly.

Set up the server-side script

Next we need to make the script that will handle the requests from the social media crawlers. Let's assume that our AngularJS app gets its data from an API. In this example, we are getting album information from the endpoint api/{id}. We can re-use this same API in our server-side script and use the data to build, on the server, our HTML page including all the social media meta tags, and output this HTML to the crawler.

An simplified PHP implementation follows:

$SITE_ROOT = "http://www.mysite.com/";

$jsonData = getData($SITE_ROOT);
makePage($jsonData, $SITE_ROOT);


function getData($siteRoot) {
    $id = ctype_digit($_GET['id']) ? $_GET['id'] : 1;
    $rawData = file_get_contents($siteRoot.'api/'.$id);
    return json_decode($rawData);
}

function makePage($data, $siteRoot) {
    ?>
    <!DOCTYPE html>
    <html>
    <head>
        <meta property="og:title" content="<?php echo $data->title; ?>" />
        <meta property="og:description" content="<?php echo $data->description; ?>" />
        <meta property="og:image" content="<?php echo $data->image; ?>" />
        <!-- etc. -->
    </head>
    <body>
        <p><?php echo $data->description; ?></p>
        <img src="<?php echo $imageUrl; ?>">
    </body>
    </html>
<?php
}

The output of this script can be tested by visiting it directly in the browser. In the example, that would be http://www.michaelbromley.co.uk/experiments/angular-social-demo/server/static-page.php?id=1

Redirect crawlers to the server-side script

Now that we have our server-side script up an running, we just need to set up the redirection. This technique requires the use of the three Apache modules mentioned earlier, and is done with an .htaccess file containing the following rule:

<ifModule mod_rewrite.c>
 RewriteEngine On

# allow social media crawlers to work by redirecting them to a server-rendered static version on the page
RewriteCond %{HTTP_USER_AGENT} (facebookexternalhit/[0-9]|Twitterbot|Pinterest|Google.*snippet)
RewriteRule album/(\d*)$ http://www.michaelbromley.co.uk/experiments/angular-social-demo/server/static-page.php?id=$1 [P]

</ifModule>

The RewriteCond link looks at the user agent string to see if it matches the following expression. The specific strings used in this expression are based on the known user agents of the various social media crawlers (at the time of this writing):

  • Facebook: facebookexternalhit/1.1 (+http(s)://www.facebook.com/externalhit_uatext.php)
  • Twitter: Twitterbot/{version}
  • Pinterest: Pinterest/0.1 +http://pinterest.com/
  • Google Plus: Google (+https://developers.google.com/+/web/snippet/)
  • Google Structured Data Testing tool: Google-StructuredDataTestingTool; +http://www.google.com/webmasters/tools/richsnippets

The [P] flag causes Apache to perform a remap using mod_proxy and mod_proxy_http, rather than a regular redirect. If a 301 redirect is used, Facebook for example will link to the "static-page.php" URL rather than the original URL.

If you are using NGINX

# NGINX location block
# this will PROXY-ly map (not 301 redirect) all the crawling requests from facebook, twitter bots... to the server that hosts
# the template for sharing. On the template, we will diplay only the meta tags in the head (See the template file in this same gist)

# This block goes first
location /cars {
  if ($http_user_agent ~* "facebookexternalhit/[0-9]|Twitterbot|Pinterest|Google.*snippet") {
    rewrite ^/cars/(.*) /cars/$1/share_for_proxy_passing break;
    proxy_pass http://the-server-that-hosts-the-template-share-for-proxy-passing.com;
  }
  rewrite ^/cars/(.*)$ /#/cars/$1 last;
}

# Then this
location / {
  try_files $uri /index.html;
}

Test it out

Now that everything is set up, it's time to test out whether it actually works as expected. All the social media sites we have mentioned so far offer some kind of validation tool that will give you an idea of what your URL will look like when shared:

Also, Fidder is a great tool for testing out this kind of thing, since you can manually set the user agent and then inspect the response from the server.

angular-social-demo's People

Contributors

michaelbromley avatar mreigen avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.