title: Facebook OG Meta with Angular and Node
body: <p>I am trying to get my angular / node application to render dynamic Open graph meta content.</p>
  
  <p>I have been trying to follow this tutorial <a href="http://www.codewarmer.com/posts/1394433236-configuring-angularjs-nodejs-for-search-bots#" rel="nofollow noreferrer">http://www.codewarmer.com/posts/1394433236-configuring-angularjs-nodejs-for-search-bots#</a>!</p>
  
  <p>I am having some problems with phantom working with node, my issue seems to be similar to this <a href="https://stackoverflow.com/questions/26468608/error-message-when-using-phantomjs-breaks-at-random-intervals">Error message when using PhantomJS, breaks at random intervals</a></p>
  
  <p>except that my error does not happen at random intervals, it happens all the time.</p>
  
  <p>EDIT: Here is my code</p>
  
  <p>In my server.js I require a module i created based on the above tut called PhantomHandler.js and it is called like so.</p>
  
  <pre><code>var crawler = require('./modules/PhantomHandler');
  </code></pre>
  
  <p>This is what PhantomHandler.js looks like:</p>
  
  <pre><code>    var phantom = require('phantom');
  var models = require('../models');
  
  mongoose = require('mongoose');
  Snapshot = models.Snapshot;
  
  url = require('url');
  var baseUrl = 'my url';
  
  function crawlSite(idx, arr, page, callback) {
      crawlUrl(arr[idx], page, function(data) {
          data.links.forEach(function(link) {
              if (arr.indexOf(link) &lt; 0)
                  arr.push(link);
          });
          Snapshot.upsert(data);
  
          if (++idx === arr.length)
              callback();
          else
              crawlSite(idx, arr, page, callback);
      });
  }
  
  function startPhantom(cb) {
      phantom.create(function(ph) {
          phInstance = ph;
          ph.createPage(function(page) {
              phPage = page;
              cb(ph, page);
          });
      });
  }
  
  function crawlUrl(path, page, cb) {
      uri = url.resolve(baseUrl, path);
  
      page.open(uri, function(status) {
          var evaluateCb = function(result) {
              result.path = path;
              cb(result);
          };
          //Timeout 2000ms seems pretty enough for majority ajax apps
          setTimeout(function() {
              if (status == 'success')
                  page.evaluate(function() {
                      var linkTags = document.querySelectorAll('a:not([rel="nofollow"])');
                      var links = [];
                      for (var i = 0, ln; ln = linkTags[i]; i++)
                          links.push(ln.getAttribute('href'));
  
                      return {
                          'links': links,
                          'html': document.documentElement.outerHTML
                      };
                  }, evaluateCb);
          }, 2000);
      });
  }
  
  exports.crawlAll = function(callback) {
      startPhantom(function(ph, page) {
          crawlSite(0, ['/'], page, function() {
              ph.exit();
              callback();
          });
      });
  };
  
  exports.crawlOne = function(path, callback) {
      startPhantom(function(ph, page) {
          crawlUrl(path, page, function(data) {
              Snapshot.upsert(data);
              ph.exit();
              callback();
          });
      });
  };
  </code></pre>
  
  <p>When i run this code my exact error is:</p>
  
  <pre><code>    phantom stderr: 'phantomjs' is not recognized as an internal or exte
  ,
  operable program or batch file.
  
  
  assert.js:92
    throw new assert.AssertionError({
          ^
  AssertionError: abnormal phantomjs exit code: 1
      at Console.assert (console.js:102:23)
      at ChildProcess.&lt;anonymous&gt; (path to node modules\node_modules\phantom\phantom.js:150:28)
      at ChildProcess.emit (events.js:98:17)
      at Process.ChildProcess._handle.onexit (child_process.js:809:12)
  </code></pre>
  
  <p>My question: Is this the best easiest way to go about getting angular to play nicely with Facebook OG? If it is can anyone else confirm if they have managed to get this technique to work with out phantom throwing an assertion error as described above. </p>
  
  <p>It seems like this should be a relatively common job and I am surprised that I haven't found a nice straight forward tutorial on how to get this to work, unless i just haven't looked properly :s</p>
  
  <p>Thanks</p>