Google Sheets er et sjitbra CMS!

kode24 bruker det til kalender, VG til koronatall. Fagredaktør Jørgen viser deg hvordan.

Vi gikk for Google Sheets som backend for vår nye kodekalender. Fagredaktør Jørgen Jacobsen forklarer hvordan. 📸-montasje: Ole Petter Baugerød Stokke / Jørgen Jacobsen
Vi gikk for Google Sheets som backend for vår nye kodekalender. Fagredaktør Jørgen Jacobsen forklarer hvordan. 📸-montasje: Ole Petter Baugerød Stokke / Jørgen Jacobsen Vis mer

Har du sittet i Teams-møter med sjefer, mellomledere eller bare en eller annen skrulle fra markedsavdelingen, og fått servert en heftig Powerpoint med en svevende produktidé som helst skal lanseres uka etter?

Som i tillegg krever at man skal kunne redigere og legge inn masse greier, skrive inn en bunch med tall og datoer i forskjellige felter, og oppdateres konstant av nettopp fyren fra markedsavdelinga?

Fortvil ikke, min venn, du trenger ikke sette opp WordPress, lære Sanity, eller snurre opp en egen LAMP-stack.

Den nye kalenderen på kode24 bruker nemlig Google Sheets som CMS, og vi lanserte den på ei uke.

Det er jæskla lett, og til og med store aviser som VG bruker det i sin koronaspesial.

La meg forklare hvordan.

Skjemaene er gull verdt

Her i kode24 bruker vi Google Sheets konstant til å organisere data - altså Google sitt regneark-alternativ til Microsoft Excel.

I Sheets-mappa vår på Google Drive finner du alt fra Kodeløkka-undersøkelsene våre om utviklere i Norge, til stemmene fra kode24-prisen 2020. Begge disse regnearkene inneholder data fra noe vi har spurt dere brukere om, og i begge tilfeller har vi brukt dataen til å lage innhold på kode24.

Men ikke direkte. Det er først vi har koblet dataene våre i Sheets direkte til kode24.no. Vi fant rett og slett ut at vi satt på et fullverdig CMS, uten å ha tenkt over det.

Det som gjør Google Sheets gull verdt i forhold til datainnsamlig er koblingen til Google Forms. Google Forms lar deg bygge et skjema, hvor du definerer alt fra dato-typer til fritekstfelt, bilder og tall, og etter hvert som data skrives inn i skjemaet settes det også inn i et Google Sheets-regneark.

Skjemaet hvor vi tar i mot oppføringer på kode24-kalenderen er laga i Google Forms. Og koblingen mellom dette og et regneark i Google Drive gjør det til et mini-CMS. 📸: Jørgen Jacobsen
Skjemaet hvor vi tar i mot oppføringer på kode24-kalenderen er laga i Google Forms. Og koblingen mellom dette og et regneark i Google Drive gjør det til et mini-CMS. 📸: Jørgen Jacobsen Vis mer

Regnearkene i Drive-en vår jeg nevnte over er begge eksempler på slike koblinger.

Du kan altså bygge et skjema med alle datafeltene du trenger, gi det til fyren på marked, og være skråsikker på at hen puncher korrekt data direkte inn i regnearket ditt.

Trenger du ekstra felt som ikke hører hjemme i skjemaet? For eksempel en toggle for publisering? Da legger du det bare til som en kolonne i regnearket.

Vipps har du et mini-CMS, som du kan redigere, sortere og duplisere som du vil. Nå trenger du bare koble dataen din til nettsiden din.

Dropp Google-biblioteker

Jeg er den første til å være enig med deg, om du synes Google er helt riv ruskende ræva på dokumentasjon av tjenestene sine. Vi slår neppe inn noen dører, hele internett et stort sett enig.

Å prøve å bruke Googles egne biblioteker og tilhørende dokumentasjon anbefaler jeg derfor å styre unna.

Bruk heller en av de åpne bibliotekene fra Github-brukere som har lidd seg gjennom Googles egne forklaringer, og pakket alt inn i et enkelt grensesnitt for deg.

I vår kalenderløsning bruker vi prosjektet node-google-spreadsheet, som kaller seg selv den mest populære Google Sheets API-wrapperen for JavaScript, og lar oss bygge et fint lite API via Node. Det finnes garantert wrappere for ditt favorittspråk, også.

Det er med god grunn at node-google-spreadsheet er populært. På bare seks linjer med kode får du tilgang til regnearket ditt, i et fint lite JavaScript-objekt. Den støtter til og med regneark med flere sider, slik at du for eksempel kan ha ett ark med data fra skjemaet ditt, og en annen side med obskur værdata. Om du ønsker det da.

const { GoogleSpreadsheet } = require("google-spreadsheet");

const getRows = async () => {
    // sheet id finner du i Google Sheets-urlen
    const SHEET_ID = process.env.SHEET_ID;
    // lag en Google Sheets representasjon
    const doc = new GoogleSpreadsheet(SHEET_ID);
    // Autentiser med nøkler du får i Googles utviklerportal
    await doc.useServiceAccountAuth({
      private_key: process.env.GOOGLE_PRIVATE_KEY.replace(/\\n/gm, "\n"),
      client_email: process.env.GOOGLE_SERVICE_ACCOUNT_EMAIL,
    });
    // last inn regnearket ditt
    await doc.loadInfo();
    // pek på første ark i Google Sheets-urlen
    const sheet = doc.sheetsByIndex[0];
    // hent radene
    const rows = await sheet.getRows();
}

Som du ser i eksempelet over trenger du også noen autentiseringsnøkler fra Google for å få dette til i virke. Via en såkalt Service Account. Det krever at du registrerer en utviklerkonto hos Google som har tilgang til regnearket, og skrur på Google Drive-API-et. Om du trenger en guide blir alt forklart detaljert i denne Medium-bloggartikkelen.

Gratis bildehostings-triks

En genial fordel med å bruke Google Forms er bildeopplasting.

I vårt kalenderskjema lar vi brukeren laste opp et bilde av arrangementet sitt. Det bildet havner i Google Drive-en vår, og vipps har vi en fiks ferdig bildehostings-tjeneste.

Det er riktig nok ikke like rett frem å implementere i koden. I regnearket som er koblet til skjemaet legges det nemlig ikke noen direktelenke til bildene, men heller en lenke til hvor bildene befinner seg i Google Drive. Fordi Google vil i utgangspunktet ikke at alle skal ha tilgang til disse bildene.

Vi derimot, trenger en lenke direkte til bildet som er åpen for alle. Det er et par krumspring du må gjennom for å konfigurere dette.

Det første du skal gjøre er å huke av for PDF eller dokumenter i tillegg til vanlige bilder som tillatte filtyper i bildeopplastingen din. Det tvinger nemlig Google Drive til å opprette en mappe for bildene dine.

Huk av PDF eller dokumenter i tillegg til bilder for å tvinge Google Drive til å opprette en mappe.
Huk av PDF eller dokumenter i tillegg til bilder for å tvinge Google Drive til å opprette en mappe. Vis mer

Deretter skal du åpne mappen og velge at alle som har lenken kan se innholdet i mappen - mappen åpner du forøvrig ved å åpne en av bildelenkene i regnearket ditt, og trykke på mappeknappen med Google Drive-ikon øverst til høyre.

Velg "Anyone on the internet with this link can view" i menypunkt to i delemenyen.
Velg "Anyone on the internet with this link can view" i menypunkt to i delemenyen. Vis mer

Dette sikrer at alle bildene i mappen, og alle som lastes opp i fremtiden kan åpnes uten at Google Drive krever rettigheter fra dem.

Deretter trenger du bare å skrive en liten kodesnutt som henter bilde-ID ut fra lenken du har i Google Sheets-regnearket ditt, og peke på Googles standard bilde-URL. Under ser du hvordan vi gjør det i kalenderkoden:

// split drive url på "=" og hent det som er etter likhetstegnet 
let photo = "https://drive.google.com/thumbnail?authuser=0&sz=w320&id=" + row.photoFromDrive.split("=")[1];

Hva vi gjorde feil

Jada, jeg ser skeptikerfjeset ditt, dette er langt fra en skuddsikker løsning.

Og neppe noe du bør pitche som en løsning til kollegaer uten at dere er innforstått med fallgruvene.

«Hvem som helst med tilgang kan fucke det opp totalt.»

For selv om data kommer inn pent og pyntelig fra skjemaet, får du ut et regneark på andre siden som hvem som helst med tilgang til kan fucke opp totalt. Du kan ikke ha for mange kokker involvert i prosjektet, og alle må være kjent med Google Sheets.

Ellers ender du fort opp med sletta rader, en luring som prøver å omorganisere hele skjemaet og brekker løsningen, eller ødelagte datofelt med feil formatering slik at new Date(datofelt) steiler i JavaScript.

Vi lærte også fort at man ikke kan stole på kolonne-overskriftene i regnearket. Om noen endrer en tittel i skjemaet, ja, så endres overskriften i regnearket også. Du må derfor ikke regne med at overskriftene kan brukes i koden din.

Heldigvis tilbyr node-google-spreadsheet å hente ut verdiene på en rad som en array istedenfor - via attributtet _rawData. Slik at de som jobber med å pusse på skjemaet kan fikle så mye de vil, så lenge de ikke endrer rekkefølgen på radene:

let eventData = row._rawData;

Det kan også være lurt å ha en liten feilsjekk før radene går rett ut på nettet. Hos oss løste vi det ved å legge til en rad med tittel "publisert", og ha en ja/nei-dropdown.

Velg raden, høyreklikk og trykk på datavalidering for å gjøre om en rad til drop-down.
Velg raden, høyreklikk og trykk på datavalidering for å gjøre om en rad til drop-down. Vis mer

Er du i tillegg obs på at det ikke er noen lagreknapp i Sheets, og at alle endringer speiles umiddelbart i API-et, ja da har du sikret deg et sjit-bra CMS.