Why build this integration?
Given the good reception of our article on integrating the Google Calendar API, today we bring you a new post about another Google API— Google Sheets. If you’re here, you already know it’s Google’s cloud spreadsheet tool.
As we’ve mentioned in other posts on our blog, it is often more cost‑effective to integrate third‑party applications than to build everything from scratch. In the case of Google Sheets, it also opens up a wide range of possibilities: we can read and write spreadsheet data programmatically through Google’s API.
The Google API ecosystem is one of the most complete—and free for private, low‑volume usage. It also provides SDKs/client libraries for the main languages, greatly simplifying integration.
Let’s begin
This article is aimed at readers familiar with the Laravel framework, so we will not show every line of code nor explain basic Laravel concepts. If you need an expert team to help with your project, contact us.
API configuration
The enabling process is very similar to what we followed for the Google Calendar API: you need a Google Cloud account, create (or reuse) a project, then enable the Google Sheets API and the Google Drive API. Drive access lets us list files and find spreadsheets; Sheets access lets us read and edit their content.
If you already configured consent screen & credentials for another API in this same project you can reuse them; otherwise:
- Configure the OAuth consent screen (Internal vs External).
- Add necessary scopes (Drive + Sheets). Internal = only Workspace org members; External = any Google user (may require verification before production publishing; during development add test users).
- Create OAuth 2.0 Client ID credentials with authorised redirect URIs (where Google returns the
code). Download the JSON file (client_secret.json) to use it later.
Time to code!
We will consume the API from a Laravel application using Google’s PHP client library: google/apiclient. This library simplifies authentication & requests.
At some point we need to request user consent— we create a client and redirect to the Auth URL:
public function getConsent()
{
$this->client = new Google\Client();
$this->client->setApplicationName('Sheets');
$this->client->setScopes($scopes);
$this->client->setAuthConfig(base_path().'/client_secret.json'); // downloaded credentials JSON
$this->client->setAccessType('offline');
$this->client->setPrompt('select_account consent');
$authUrl = $this->client->createAuthUrl();
return redirect()->to($authUrl);
}
We include the client_secret.json file (or better: path via env variable) so the client library can authenticate.
After the user grants Drive/Sheets permissions, Google redirects to our endpoint with a temporary code which we exchange for tokens:
public function storeToken(Request $request)
{
$scopes = [\Google_Service_Drive::DRIVE];
$this->client = new Google\Client();
$this->client->setApplicationName('Your Cloud App Name');
$this->client->setScopes($scopes);
$this->client->setAuthConfig(base_path().'/client_secret.json');
$this->client->setAccessType('offline');
$this->client->setPrompt('select_account consent');
$code = $request->only('code');
$token = $this->client->fetchAccessTokenWithAuthCode($code['code']);
GoogleToken::updateOrCreate(['token_type' => $token['token_type']], $token);
}
Now we can list spreadsheets in the user’s Drive (filter by MIME type):
public function getSheets()
{
$drive = new \Google_Service_Drive($this->client);
$sheetsList = $drive->files->listFiles([
'q' => "mimeType='application/vnd.google-apps.spreadsheet'",
'fields' => 'nextPageToken, files(id, name)'
]);
return $sheetsList;
}
To fetch a single sheet (full metadata + grid data):
public function getSheet($id)
{
$service = new \Google_Service_Sheets($this->client);
$sheet = $service->spreadsheets->get($id, ['includeGridData' => true]);
return $sheet;
}
To read cell values in a specific range:
function getValues($sheetId, $range)
{
$service = new \Google_Service_Sheets($this->client);
$result = $service->spreadsheets_values->get($sheetId, $range);
try {
$numRows = $result->getValues() !== null ? count($result->getValues()) : 0;
return $result; // $result->getValues() is an array of row arrays
} catch (Exception $e) {
echo 'Message: '.$e->getMessage();
}
}
$range follows the pattern SheetName!A1:D2 or simply SheetName (the latter returns the entire used region). Range syntax docs: reference.
Writing values:
// valueInputOption RAW = literal insert; USER_ENTERED lets Sheets parse formulas/dates.
function updateValues($spreadsheetId, $range, $valueInputOption = 'RAW')
{
try {
$values = [
[4, 3, 2, 1],
[1, 2, 3, 4]
];
$body = new \Google_Service_Sheets_ValueRange([
'values' => $values
]);
$params = [ 'valueInputOption' => $valueInputOption ];
$result = $service->spreadsheets_values->update(
$spreadsheetId, $range, $body, $params
);
return $result;
} catch (Exception $e) {
echo 'Message: '.$e->getMessage();
}
}
Key point: build the request body using Google_Service_Sheets_ValueRange, passing a 2‑D array (outer = rows, inner = cells). valueInputOption controls how Sheets interprets values.
More concepts in the official documentation.
Conclusions
If you need an experienced team for this type of integration, contact us. We’ll be glad to help you leverage Google’s ecosystem safely and efficiently.