Tuesday 8 November 2011

Pulling Blogger content into Google Sites with Google Apps Script

You may remember that I migrated the Heswall Disabled Children's Holiday Fund website to Google Apps a couple of weeks ago, and started to use Google Sites for the web pages.

One of the things I'd been wanting to do for the camp is create a blog where news and developments can be published. Google Sites offers an "Announcement" page type, but it's not really as nice to work with a Blogger, as I had discovered here already. But the trouble with trying to combine a Blogger blog with a Google Sites website, is that both use templates neither of which can easily be made to be part of the other.

The solution I came up with is to use Blogger for writing the blog, but have the RSS feed published into a Google Sites page. Conveniently, Google provides a scripting toolset, Google Apps Script (apparently this doesn't have anything to do with Google Apps, the service, but with Google apps, the suite of applications), that allows JavaScript access to the Sites object model (amongst other things).

Here's the script I came up with:

function loadContent() {
  // ... Initialisation ...
  
  var feedDocument = Xml.parse(UrlFetchApp.fetch(rssUrl).getContentText(), false);
  var feedUpdated = feedDocument.feed.updated.getText();
  var pageUpdated = CacheService.getPublicCache().get("updated");
  
  CacheService.getPublicCache().put("updated", feedUpdated, 4800);

  if (feedUpdated == pageUpdated) {
    return;
  }
  
  var site = SitesApp.getSite(domainName, siteName);
  var page = site.getChildByName(pageName);
  var template = getTemplate(site.getTemplates());
  
  var entriesArray = feedDocument.getElement().getElements("entry");
  var newPageHTML = "";
  for (var i = 0; i < entriesArray.length && i < numberPosts; i++) {
    var entry = entriesArray[i];

    newPageHTML = newPageHTML + "<div>"+
      "<h3><a href='"+getLink(entry)+"'>"+entry.title.getText()+"</a></h3>"+
      "<p>"+entry.content.getText()+"</p>"+
      "<div style='font-size:0.8em;background-color:#E7E7E7'>Posted by "+entry.author.name.getText()+" on "+getDate(entry)+"</div>"+
      "</div>";
  }
  
  if (entriesArray.length > numberPosts) {
    newPageHTML = newPageHTML + "<p><a href='"+blogspotUrl+"'>View older posts</a></p>";
  }
  
  newPageHTML = newPageHTML + "<p><a href='"+rssUrl+"'>Subscribe to Posts (Atom)</a></p>"
      
  page.setHtmlContent(template.getHtmlContent().replace(/<br[^>]*>/i, newPageHTML));
}

function getTemplate(templates) {
  var templateName = ScriptProperties.getProperty("templateName");
  for (var i = 0; i < templates.length; i++) {
    var t = templates[i];
    if (t.getPageType() == PageType.WEB_PAGE && t.getName() == templateName) {
      return t;
    }
  }
}

function getLink(entry) { ... } // Gets the right link from the entry
function getDate(entry) { ... } // Parses and formats the published date
Pretty simple, and seems to work ok. Admittedly at the time of writing, there's only one entry to publish, but I don't think more should be a problem.

No comments:

Post a Comment