Utilizing Google Drive as a CMS

No Comments

We’re going to stroll via the technical technique of hooking into Google Drive’s API to supply content material on a web site. We’ll study the step-by-step implementation, in addition to how you can make the most of server-side caching to keep away from the most important pitfalls to keep away from equivalent to API utilization limits and picture hotlinking. A ready-to-use npm package deal, Git repo, and Docker picture are offered all through the article.

However… why?

Sooner or later within the improvement of a web site, a crossroads is reached: how is content material managed when the individual managing it isn’t technically savvy? If the content material is managed by builders indefinitely, pure HTML and CSS will suffice — however this prevents wider crew collaboration; moreover, no developer desires to be on the hook for content material updates in perpetuity.

So what occurs when a brand new non-technical associate wants to realize edit entry? This might be a designer, a product supervisor, a advertising and marketing individual, an organization government, and even an finish buyer.

That’s what content material administration system is for, proper? Perhaps one thing like WordPress. However this comes with its personal arrange of disadvantages: it’s a brand new platform to your crew to juggle, a brand new interface to be taught, and a brand new vector for potential attackers. It requires creating templates, a format with its personal syntax and idiosyncrasies. Customized or third-party plugins might should be to vetted, put in, and configured for distinctive use instances — and every of those is one more supply of complexity, friction, technical debt, and danger. The bloat of all this setup might find yourself cramping your tech in a manner which is counterproductive to the precise goal of the web site.

What if we might pull content material from the place it already is? That’s what we’re getting at right here. Lots of the locations the place I’ve labored use Google Drive to prepare and share information, and that features issues like weblog and touchdown web page content material drafts. May we make the most of Google Drive’s API to import a Google Doc immediately right into a website as uncooked HTML, with a easy REST request?

In fact we are able to! Right here’s how we did it the place I work.

What you’ll want

Just some issues you could need to try as we get began:

GitHub repoNPM package dealDocker pictureHeroku demo

Authenticating with the Google Drive API

Step one is to determine a connection to Google Drive’s API, and for that, we might want to do some form of authentication. That’s a requirement to make use of the Drive API even when the information in query are publicly shared (with “hyperlink sharing” turned on). Google helps a number of strategies of doing this. The most typical is OAuth, which prompts the person with a Google-branded display saying, “[So-and-so app] desires to entry your Google Drive” and waits for person consent — not precisely what we want right here, since we’d prefer to entry information in a single central drive, slightly than the person’s drive. Plus, it’s a bit tough to offer entry to solely explicit information or folders. The https://www.googleapis.com/auth/drive.readonly scope we would use is described as:

See and obtain all of your Google Drive information.

That’s precisely what it says on the consent display. That is probably alarming for a person, and extra to the purpose, it’s a potential safety weak spot on any central developer/admin Google account that manages the web site content material; something they will entry is uncovered via the positioning’s CMS again finish, together with their very own paperwork and something shared with them. Not good!

Enter the “Service account”

As an alternative, we are able to make use of a barely much less widespread authentication technique: a Google service account. Consider a service account like a dummy Google account used completely by APIs and bots. Nevertheless, it behaves like a first-class Google account; it has its personal electronic mail handle, its personal tokens for authentication, and its personal permissions. The large win right here is that we make information accessible to this dummy service account similar to another person — by sharing the file with the service account’s electronic mail handle, which seems one thing like this:

google-drive-cms-example@npm-drive-cms.iam.gserviceaccount.com

After we go to show a doc or sheet on the web site, we merely hit the “Share” button and paste in that electronic mail handle. Now the service account can see solely the information or folders we’ve explicitly shared with it, and that entry might be modified or revoked at any time. Good!

Making a service account

A service account might be created (without cost) from the Google Cloud Platform Console. That course of is nicely documented in Google’s developer sources, and as well as it’s described in step-by-step element within the companion repo of this text on GitHub. For the sake of brevity, let’s fast-forward to right away after a profitable authentication of a service account.

The Google Drive API

Now that we’re in, we’re prepared to begin tinkering with what the Drive API is able to. We are able to begin from a modified model of the Node.js quickstart pattern, adjusted to make use of our new service account as an alternative of consumer OAuth. That’s dealt with within the first a number of strategies of the driveAPI.js we’re establishing to deal with all of our interactions with the API. The important thing distinction from Google’s pattern is within the authorize() technique, the place we use an occasion of jwtClient slightly than the oauthClient utilized in Google’s pattern:

authorize(credentials, callback) {
const { client_email, private_key } = credentials;

const jwtClient = new google.auth.JWT(client_email, null, private_key, SCOPES)

// Test if we’ve got beforehand saved a token.
fs.readFile(TOKEN_PATH, (err, token) => {
if (err) return this.getAccessToken(jwtClient, callback);
jwtClient.setCredentials(JSON.parse(token.toString()));
console.log(‘Token loaded from file’);
callback(jwtClient);
});
}

Node.js vs. client-side

Yet one more word in regards to the setup right here — this code is meant to be referred to as from server-side Node.js code. That’s as a result of the consumer credentials for the service account should be stored secret, and never uncovered to customers of our web site. They’re stored in a credentials.json file on the server, and loaded by way of fs.readFile inside Node.js. It’s additionally listed within the .gitignore to maintain the delicate keys out of supply management.

Fetching a doc

After the stage is about, loading uncooked HTML from a Google Doc turns into pretty easy. A technique like this returns a Promise of an HTML string:

getDoc(id, skipCache = false) {
return new Promise((resolve, reject) => {
this.drive.information.export({
fileId: id,
mimeType: “textual content/html”,
fields: “knowledge”,
}, (err, res) => {
if (err) return reject(‘The API returned an error: ‘ + err);
resolve({ html: this.rewriteToCachedImages(res.knowledge) });
// Cache pictures
this.cacheImages(res.knowledge);
});
});
}

The Drive.Recordsdata.export endpoint does all of the work for us right here. The id we’re passing in is simply what reveals up in your browsers handle bar whenever you open the doc, which is proven instantly after https://docs.google.com/doc/d/.

Additionally discover the 2 traces about caching pictures — this can be a particular consideration we’ll skip over for now, and revisit intimately within the subsequent part.

Right here’s an instance of a Google doc displayed externally as HTML utilizing this technique.

Fetching a sheet

Fetching Google Sheets is sort of as straightforward utilizing Spreadsheets.values.get. We modify the response object just a bit bit to transform it to a simplified JSON array, labeled with column headers from the primary row of the sheet.

getSheet(id, vary) {
return new Promise((resolve, reject) => {
this.sheets.spreadsheets.values.get({
spreadsheetId: id,
vary: vary,
}, (err, res) => {
if (err) reject(‘The API returned an error: ‘ + err);
// console.log(res.knowledge.values);
const keys = res.knowledge.values[0];
const reworked = [];
res.knowledge.values.forEach((row, i) => {
if(i === 0) return;
const merchandise = {};
row.forEach((cell, index) => {
merchandise[keys[index]] = cell;
});
reworked.push(merchandise);
});
resolve(reworked);
});
});
}

The id parameter is similar as for a doc, and the brand new vary parameter right here refers to a spread of cells to fetch values from, in Sheets A1 notation.

Instance: this Sheet is learn and parsed with the intention to render customized HTML on this web page.

…and extra!

These two endpoints already get you very far, and kinds the spine of a customized CMS for a web site. However, actually, it solely faucets the floor of Drive’s potential for content material administration. It’s additionally able to:

itemizing all information in a given folder and show them in a menu,importing advanced media from a Google Slides presentation, anddownloading and caching customized information.

The one limits listed here are your creativity, and the constraints of the complete Drive API documented right here.

Caching

As you’re enjoying with the assorted sorts of queries that the Drive API helps, you could find yourself receiving a “Person Charge Restrict Exceeded” error message . It’s pretty straightforward to hit this restrict via repeated trial-and-error testing in the course of the improvement part, and at first look, it appears as if it could characterize a tough blocker for our Google Drive-CMS technique.

That is the place caching is available in — each time we fetch a new model of any file on Drive, we cache it domestically (aka server-side, throughout the Node.js course of). As soon as we try this, we solely must examine the model of each file. If our cache is old-fashioned, we fetch the latest model of the corresponding file, however that request solely occurs as soon as per file model, slightly than as soon as per person request. As an alternative of scaling by the quantity of people that use the web site, we are able to now scale by the variety of updates/edits on Google Drive as our limiting issue. Underneath the present Drive utilization limits on a free-tier account, we might help as much as 300 API requests per minute. Caching ought to preserve us nicely inside this restrict, and it might be optimized even additional by batching a number of requests.

Dealing with pictures

The identical caching technique is utilized to photographs embedded inside Google Docs. The getDoc technique parses the HTML response for any picture URLs, and makes a secondary request to obtain them (or fetches them immediately from cache in the event that they’re already there). Then it rewrites the unique URL within the HTML. The result’s that static HTML; we by no means use hotlinks to Google picture CDNs. By the point it will get to the browser, the pictures have already been pre-cached.

Respectful and responsive

Caching ensures two issues: first, that we’re being respectful of Google’s API utilization limits, and really make the most of Google Drive as a entrance finish for modifying and file administration (what the software is meant for), slightly than leaching off of it without cost bandwidth and cupboard space. It retains our web site’s interplay with Google’s APIs to the naked minimal essential to refresh the cache as wanted.

The opposite profit is one which the customers of our web site will take pleasure in: a responsive web site with minimal load occasions. Since cached Google Docs are saved as static HTML on our personal server, we are able to fetch them instantly with out ready for a third-party REST request to finish, maintaining web site load occasions to a minimal.

Wrapping in Specific

Since all this tinkering has been in server-side Node.js, we want a manner for our consumer pages to work together with the APIs. By wrapping the DriveAPI into its personal REST service, we are able to create a intermediary/proxy service which abstracts away all of the logic of caching/fetching new variations, whereas maintaining the delicate authentication credentials secure on the server facet.

A sequence of categorical routes, or the equal in your favourite internet server, will do the trick, with a sequence of routes like this:

const driveAPI = new (require(‘./driveAPI’))();
const categorical = require(‘categorical’);
const API_VERSION = 1;
const router = categorical.Router();

router.route(‘/getDoc’)
.get((req, res) => {
console.log(‘GET /getDoc’, req.question.id);
driveAPI.getDoc(req.question.id)
.then(knowledge => res.json(knowledge))
.catch(error => {
console.error(error);
res.sendStatus(500);
});
});

// Different routes included right here (getSheet, getImage, listFiles, and so forth)…

app.use(`/api/v${API_VERSION}`, router);

See the complete categorical.js file within the companion repo.

Bonus: Docker Deployment

For deployment to manufacturing, we are able to can run the Specific server alongside your present static internet server. Or, if it’s handy, we might simply wrap it in a Docker picture:

FROM node:8
# Create app listing
WORKDIR /usr/src/app
# Set up app dependencies
# A wildcard is used to make sure each package deal.json AND package-lock.json are copied
# the place accessible (npm@5+)
COPY package deal*.json ./
RUN npm set up
# If you’re constructing your code for manufacturing
# RUN npm ci –only=manufacturing
# Bundle app supply
COPY . .
CMD [ “node”, “express.js” ]

…or use this pre-built picture printed on Docker Hub.

Bonus 2: NGINX Google OAuth

In case your web site is public-facing (accessible by anybody on the web), then we’re accomplished! However for our functions the place I work at Motorola, we’re publishing an internal-only documentation website that wants extra safety. Meaning Hyperlink Sharing is turned off on all our Google Docs (in addition they occurred to be saved in an remoted and devoted Google Staff Drive separated from all different firm content material).

We dealt with this extra layer of safety as early as potential on the server stage, utilizing NGINX to intercept and reverse-proxy all requests earlier than they even make it to the Specific server or any static content material hosted by the web site. For this, we use Cloudflare’s wonderful Docker picture to current a Google sign-on display to all workers accessing any web site sources or endpoints (each the Drive API Specific server and the static content material alongside it). It seamlessly integrates with the company Google account and single-sign-on they have already got — no further account wanted!

Conclusion

Every little thing we simply lined on this article is strictly what we’ve accomplished the place I work. It’s a light-weight, versatile, and decentralized content material administration structure, through which the uncooked knowledge lives the place Google Drive, the place our crew already works, utilizing a UI that’s already acquainted to everybody. All of it will get tied collectively into the web site’s entrance finish which retains the complete flexibility of pure HTML and CSS by way of management over presentation, and with minimal architectural constraints. Just a little further legwork from you, the developer, creates a nearly seamless expertise for each your non-dev collaborators and your finish customers alike.

Will this type of factor work for everybody? In fact not. Totally different websites have totally different wants. But when I had been to place collectively an inventory of use instances for when to make use of Google Drive as a CMS, it could look one thing like this:

An inside website with between a couple of hundred to a couple thousand each day customers — If this had been the entrance web page of the worldwide firm web site, even a single request for file model metadata per person may strategy that Drive API utilization restrict. Additional methods might assist mitigate that — but it surely’s the most effective match for small to medium-size web sites.A single-page app — This setup has allowed us to question the model numbers of each knowledge supply in a single REST request, one time per session, slightly than one time per web page. A non-single-page app might use the identical strategy, even perhaps making use of cookies or native storage to perform the identical “as soon as per go to” model question, however once more, it could take a bit of further legwork.A crew that’s already utilizing Google Drive — Maybe most vital of all, our collaborators had been pleasantly stunned that they may contribute to the web site utilizing an account and workflow they already had entry to and had been snug utilizing, together with the entire refinements of Google’s WYSIWYG expertise, highly effective entry administration, and the remainder.

The publish Utilizing Google Drive as a CMS appeared first on CSS-Tips. You’ll be able to help CSS-Tips by being an MVP Supporter.

    About Marketing Solution Australia

    We are a digital marketing company with a focus on helping our customers achieve great results across several key areas.

    Request a free quote

    We offer professional SEO services that help websites increase their organic search score drastically in order to compete for the highest rankings even when it comes to highly competitive keywords.

    Subscribe to our newsletter!

    More from our blog

    See all posts

    Leave a Comment