Michiu / marketing reference

Google Business Profile — review import setup

One-time setup to pull all Michiu's Google reviews + existing replies into the review system using Google's official APIs (no scraping).

Total operator time: ~15 min hands-on + however long Google takes to approve the API access form (typically hours, sometimes days).


What this does

pnpm import:google connects to Google Business Profile as the verified Michiu owner, fetches every review via the official Reviews API, and writes them into the review system. Existing merchant replies are preserved as status='posted'. Reviews without a reply land as status='new' and surface in the admin inbox for AI variant generation on demand.

It's idempotent — re-running picks up only new reviews and updates existing ones in place.


Prerequisites

  • A Google account that is a verified owner or manager of "Restaurant Michiu" on Google Business Profile (at the time of writing: csprkrn@gmail.com)
  • Access to Google Cloud Console with that same account
  • Node 22+, pnpm 9+ (already required by the repo)

Step 1 — Create or pick a Google Cloud project

  1. Sign in at https://console.cloud.google.com as the verified owner account
  2. Create a new project (e.g. "Michiu Marketing") or pick an existing one
  3. Note the project number (top of the dashboard) — you'll need it for step 3

Step 2 — Enable the required APIs

In the project, enable all three of these:

  • My Business Account Management APImybusinessaccountmanagement.googleapis.com
  • My Business Business Information APImybusinessbusinessinformation.googleapis.com
  • My Business Q&A APImybusinessqanda.googleapis.com

(The Q&A API isn't used by this importer, but Google's access form requires several My Business APIs to be enabled before approval.)

Enable via APIs & Services → Library, search each name, click Enable.


Step 3 — Apply for Business Profile API access

This is the slow part. Google requires a separate approval beyond just enabling the APIs — they want to verify the requester is a legitimate business owner.

  1. Open https://developers.google.com/my-business/content/prereqs
  2. Follow the "Request access to the Google Business Profile API" link
  3. Provide:
    • The project number from step 1
    • A 1-line use-case description, e.g. "Pulling our restaurant's review history into our internal admin tool."
    • The contact email
  4. Submit and wait for the approval email

Until approved: pnpm google:auth works (OAuth itself doesn't need approval), but pnpm import:google will return HTTP 403 with a PERMISSION_DENIED body. The error handler surfaces a hint explaining this.


Step 4 — Create OAuth 2.0 credentials

In the same project, APIs & Services → Credentials:

  1. Click Create CredentialsOAuth client ID
  2. If prompted, configure the consent screen first:
    • User Type: External
    • App name: "Michiu Reviews Importer" (or anything)
    • User support email: the verified owner email
    • Developer contact: same
    • Scopes: leave default (you'll request business.manage at runtime)
    • Test users: add the verified owner email
  3. Application type: Desktop app
  4. Name: "Michiu importer"
  5. Save the Client ID and Client Secret

Step 5 — Wire credentials and run the OAuth flow

In ~/Code/michiu-marketing/.env.local:

GOOGLE_OAUTH_CLIENT_ID=<paste-from-step-4>
GOOGLE_OAUTH_CLIENT_SECRET=<paste-from-step-4>

Then run:

pnpm google:auth

The script:

  1. Prints a Google sign-in URL — open it in a browser
  2. Sign in as the verified owner account (csprkrn@gmail.com)
  3. Click Allow to grant business.manage scope
  4. Google redirects to http://localhost:8788?code=…; the script captures it
  5. Exchanges for a refresh token and writes it to .env.local under GOOGLE_OAUTH_REFRESH_TOKEN (idempotent — re-runs replace the line)

Step 6 — Run the import

pnpm import:google

On a single-business owner account, the importer auto-discovers the account and location. If the owner has multiple businesses, the script prints the candidates and asks you to pin one via env:

GOOGLE_ACCOUNT_ID=123456789012345678901
GOOGLE_LOCATION_ID=987654321098765432109

Sample output:

[import:google] Imported from accounts/123… / Restaurant Michiu (account 123…, location 987…)

  Reviews fetched:    142
  Reviews created:    142
  Reviews updated:    0
  Replies imported:   97   (existing merchant replies)
  Awaiting reply:     45

[import:google] Open http://localhost:3000/admin/reviews to review.

Re-running the import

Safe and idempotent. Each call:

  • Updates rating/text/raw_payload of any review whose Google updateTime changed
  • Adds new reviews that appeared since last run
  • Preserves locally-approved replies and previously-imported merchant replies (deduped by reply text)

You can run this on a cron once Phase 2 (Supabase + auth) lands.


Troubleshooting

SymptomLikely cause + fix
pnpm google:auth says "Google did not return a refresh_token"You already have a grant. Revoke at https://myaccount.google.com/permissions and re-run.
pnpm import:google returns HTTP 401Refresh token rejected. Re-run pnpm google:auth.
HTTP 403 with "API has not been used" or PERMISSION_DENIEDBusiness Profile API access not yet approved (step 3) OR the relevant My Business API isn't enabled in the project.
HTTP 403 with "User is not authorized"The signed-in account isn't a verified owner/manager of the Michiu listing.
HTTP 404 on locations or reviewsGOOGLE_ACCOUNT_ID / GOOGLE_LOCATION_ID is wrong. Unset them and let auto-discovery run.
HTTP 429Rate limit. Default Business Profile quota is ~10 req/min. Wait and re-run.
Multiple accounts/locations errorPin the right one via GOOGLE_ACCOUNT_ID / GOOGLE_LOCATION_ID env vars.

Security

  • .env.local is gitignored. The refresh token never lands in a commit.
  • The OAuth scope is read-only as far as this importer cares (we never call reviewReply.create). Phase 2 may add reply-posting; document that change when it happens.
  • To revoke access entirely: https://myaccount.google.com/permissions → remove the OAuth client.

Source: michiu-marketing/docs/google-business-profile-setup.md. To edit, change the file in the repo and redeploy.