-
Notifications
You must be signed in to change notification settings - Fork 5.5k
Google Business new components #18074
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. 3 Skipped Deployments
|
WalkthroughAdds Google My Business review actions and sources, app endpoints and request/response types, multiple metadata version bumps, and a small error-message enhancement to JSON parse errors in the create-post action. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant Action as PD Action
participant App as GMB App
participant GoogleAPI as Google My Business API
User->>Action: Run "Get Reviews from Multiple Locations"
Action->>App: batchGetReviews({ account, data: { locationNames[], pageSize, orderBy, ... } })
App->>GoogleAPI: POST /v4/accounts/{account}/locations:batchGetReviews
GoogleAPI-->>App: BatchGetReviewsResponse
App-->>Action: response
Action-->>User: Export summary + return response
sequenceDiagram
participant Source as New Review Source
participant App as GMB App
participant GoogleAPI as Google My Business API
participant Workflow as PD Workflow
Source->>App: batchGetReviews({ account, data: { locationNames[] } })
App->>GoogleAPI: POST /v4/accounts/{account}/locations:batchGetReviews
GoogleAPI-->>App: locationReviews[]
App-->>Source: locationReviews
Source->>Workflow: Emit events per review (with summary)
sequenceDiagram
participant User
participant Action as PD Action
participant App as GMB App
participant GoogleAPI as Google My Business API
User->>Action: Run "Get a Specific Review"
Action->>App: getReview({ account, location, review })
App->>GoogleAPI: GET /v4/accounts/{a}/locations/{l}/reviews/{r}
GoogleAPI-->>App: Review
App-->>Action: Review
Action-->>User: Export summary + return Review
sequenceDiagram
participant User
participant Action as PD Action
participant App as GMB App
participant GoogleAPI as Google My Business API
User->>Action: Run "List All Reviews"
Action->>App: listReviews({ account, location })
App->>GoogleAPI: GET /v4/accounts/{a}/locations/{l}/reviews
GoogleAPI-->>App: Review[]
App-->>Action: Review[]
Action-->>User: Export summary + return Review[]
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Assessment against linked issues
Out-of-scope changes
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. 📜 Recent review detailsConfiguration used: CodeRabbit UI 💡 Knowledge Base configuration:
You can enable these sources in your CodeRabbit configuration. 📒 Files selected for processing (4)
🚧 Files skipped from review as they are similar to previous changes (4)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (4)
components/google_my_business/actions/create-post/create-post.ts (1)
97-99: Fix ESLint failure: remove unused catch parameterCI is failing with no-unused-vars for
err. It's not used; remove the binding or use a leading underscore depending on lint config. Prefer empty catch for clarity.Apply this diff:
- } catch (err) { + } catch { throw new ConfigurationError(`**Invalid JSON string** for object prop: "${obj}"`); }components/google_my_business/app/google_my_business.app.ts (3)
135-142:pageSizeis not being sent: it must be insideparams
_httpRequestforwardsparamsto axios as query params. The current top-levelpageSizeis ignored, so the API will not receive it.const response = await this._httpRequest({ url: `https://mybusinessbusinessinformation.googleapis.com/v1/accounts/${account}/locations`, - pageSize: 100, params: { filter, readMask: "name,title", + pageSize: 100, }, });
148-151:pageSizeis not being sent in List Reviews requestSame issue:
pageSizemust be underparamsto be sent as a query parameter. Currently ignored by axios.const response = await this._httpRequest({ url: `https://mybusiness.googleapis.com/v4/accounts/${account}/locations/${location}/reviews`, - pageSize: 50, + params: { + pageSize: 50, + }, });
165-168:pageSizeis not being sent in List Posts (non-paginated path)When
paginateis false,pageSizemust also be set insideparams.const response: { localPosts?: LocalPost[]; } = await this._httpRequest({ url, - pageSize: 100, + params: { + pageSize: 100, + }, });
🧹 Nitpick comments (12)
components/google_my_business/actions/create-post/create-post.ts (1)
102-110: Validate media/mediaFormat pairing (avoid API errors)Per your prop description, media requires mediaFormat and vice versa. Currently,
mediacan be sent withmediaFormatundefined. Add a quick guard to fail fast with a helpful error.Apply this diff to add validation just after destructuring:
async run({ $ }) { const { account, location, topicType, languageCode, summary, media, mediaFormat, alertType, } = this; + if (media?.length && !mediaFormat) { + throw new ConfigurationError("Media Format is required when Media is provided."); + } + if (!media?.length && mediaFormat) { + throw new ConfigurationError("Media is required when Media Format is provided."); + }components/google_my_business/common/requestParams.ts (2)
58-66: ConstrainorderByto known API valuesUsing a union tightens types and prevents invalid strings at compile time.
export interface BatchGetReviewsParams extends PdAxiosRequest { account: string; data: { locationNames: string[]; pageSize?: number; pageToken?: string; - orderBy?: string; + orderBy?: "createTime desc" | "createTime asc" | "updateTime desc" | "updateTime asc"; ignoreRatingOnlyReviews?: boolean; }; }
67-67: Fix linter error: add a newline at EOFThis addresses the “Newline required at end of file” failure.
} +components/google_my_business/app/google_my_business.app.ts (3)
66-71: Type mismatch: mapping reviews asLocationThe
reviewprop options mapper is typed asLocationbut processes reviews. UseReviewfor correct typing.- }: Location) => ({ + }: Review) => ({ label: title, value: this.getCleanName(name) as string, }));
119-123: Optional: count actual items returned to control pagination more accuratelyIncrementing by
pageSizecan prematurely stop fetching if fewer items are returned than requested. Use the length ofresourcesinstead.- resultCount += pageSize; + resultCount += Array.isArray(resources) ? resources.length : 0;
198-206: Return a strongly typed response forbatchGetReviewsYou’ve defined
BatchGetReviewsResponse; returning it here improves type safety downstream.- }: BatchGetReviewsParams): Promise<object> { + }: BatchGetReviewsParams): Promise<BatchGetReviewsResponse> { return this._httpRequest({ method: "POST", url: `https://mybusiness.googleapis.com/v4/accounts/${account}/locations:batchGetReviews`, ...args, }); },Also add the import:
- At the import from
../common/responseSchemas, includeBatchGetReviewsResponse.Example:
import { Account, LocalPost, Location, Review, BatchGetReviewsResponse, } from "../common/responseSchemas";components/google_my_business/actions/get-specific-review/get-specific-review.ts (1)
55-59: Nit: make the summary more robustIf available, include the returned resource name. Falls back to the input
reviewid.- $.export("$summary", `Successfully retrieved review: ${review}`); + $.export("$summary", `Successfully retrieved review: ${response?.name ?? review}`);components/google_my_business/actions/get-reviews-multiple-locations/get-reviews-multiple-locations.ts (3)
49-49: Fix linter error: trailing whitespaceRemove the trailing space after
"createTime asc".- "createTime asc", + "createTime asc",
71-76: Prefer failing fast: makelocationNamesrequired (remove optional chaining)This prop is conceptually required; mapping with
?.can hide missing input and result in an invalid payload. Also aligns with the summary that assumes a value.- locationNames: locationNames?.map((locationName: string) => `accounts/${account}/locations/${locationName}`), + locationNames: locationNames.map((locationName: string) => `accounts/${account}/locations/${locationName}`),If you want to keep it defensive, consider validating and throwing a clear error when empty.
80-80: Guard summary when input might be emptyDefensive tweak to avoid a runtime error if
locationNamesis unexpectedly undefined.- $.export("$summary", `Successfully retrieved reviews from ${locationNames.length} locations`); + $.export("$summary", `Successfully retrieved reviews from ${locationNames?.length ?? 0} locations`);components/google_my_business/sources/new-review-created-multiple-locations/new-review-created-multiple-locations.ts (2)
3-3: Fix lint: break named import across linesStatic analysis flagged object-curly-newline issues. Break the named import onto multiple lines to satisfy the style rule.
-import { BatchGetReviewsResponse, Review } from "../../common/responseSchemas"; +import { + BatchGetReviewsResponse, + Review, +} from "../../common/responseSchemas";
19-30: Confirm multi-select behavior of thelocationpropDefinition
Please verify that in the PropDog UI (or with a quick local script) thelocationprop incomponents/google_my_business/app.ts:
- Renders as a multi‐select when used with
type: "string[]", and- Returns the expected strings—either fully-qualified names (
accounts/{account}/locations/{locationId}) or bare IDs.Depending on what you get:
- If it already returns fully-qualified names, remove any extra prefix logic to avoid double-prefixing.
- If it returns only raw IDs, prefix each value with
accounts/{account}/locations/before use.Let me know what the prop yields so we can finalize the mapping logic.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (13)
components/google_my_business/actions/create-post/create-post.ts(1 hunks)components/google_my_business/actions/create-update-reply-to-review/create-update-reply-to-review.ts(1 hunks)components/google_my_business/actions/get-reviews-multiple-locations/get-reviews-multiple-locations.ts(1 hunks)components/google_my_business/actions/get-specific-review/get-specific-review.ts(1 hunks)components/google_my_business/actions/list-all-reviews/list-all-reviews.ts(1 hunks)components/google_my_business/actions/list-posts/list-posts.ts(1 hunks)components/google_my_business/app/google_my_business.app.ts(2 hunks)components/google_my_business/common/requestParams.ts(1 hunks)components/google_my_business/common/responseSchemas.ts(1 hunks)components/google_my_business/package.json(1 hunks)components/google_my_business/sources/new-post-created/new-post-created.ts(1 hunks)components/google_my_business/sources/new-review-created-multiple-locations/new-review-created-multiple-locations.ts(1 hunks)components/google_my_business/sources/new-review-created/new-review-created.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (5)
components/google_my_business/actions/get-reviews-multiple-locations/get-reviews-multiple-locations.ts (1)
components/google_my_business/common/requestParams.ts (1)
BatchGetReviewsParams(58-67)
components/google_my_business/actions/list-all-reviews/list-all-reviews.ts (1)
components/google_my_business/common/requestParams.ts (1)
ListReviewsParams(32-32)
components/google_my_business/actions/get-specific-review/get-specific-review.ts (1)
components/google_my_business/common/requestParams.ts (1)
GetReviewParams(54-56)
components/google_my_business/app/google_my_business.app.ts (2)
components/google_my_business/common/requestParams.ts (2)
GetReviewParams(54-56)BatchGetReviewsParams(58-67)components/google_my_business/common/responseSchemas.ts (1)
Review(18-21)
components/google_my_business/sources/new-review-created-multiple-locations/new-review-created-multiple-locations.ts (2)
components/google_my_business/common/responseSchemas.ts (2)
Review(18-21)BatchGetReviewsResponse(26-30)components/google_my_business/common/requestParams.ts (1)
BatchGetReviewsParams(58-67)
🪛 GitHub Check: Lint Code Base
components/google_my_business/common/requestParams.ts
[failure] 67-67:
Newline required at end of file but not found
components/google_my_business/actions/get-reviews-multiple-locations/get-reviews-multiple-locations.ts
[failure] 49-49:
Trailing spaces not allowed
components/google_my_business/sources/new-review-created-multiple-locations/new-review-created-multiple-locations.ts
[failure] 3-3:
Expected a line break before this closing brace
[failure] 3-3:
Expected a line break after this opening brace
🪛 GitHub Actions: Pull Request Checks
components/google_my_business/actions/create-post/create-post.ts
[error] 97-97: ESLint: 'err' is defined but never used. (no-unused-vars)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Publish TypeScript components
- GitHub Check: Verify TypeScript components
🔇 Additional comments (12)
components/google_my_business/actions/create-update-reply-to-review/create-update-reply-to-review.ts (1)
11-11: Version bump only — LGTMNo functional changes. Version aligns with the package bump and broader review-related additions in this PR.
components/google_my_business/package.json (1)
3-3: Version bump looks consistent"0.2.0" aligns with the added review functionality and other action/source version bumps. No issues spotted.
components/google_my_business/sources/new-review-created/new-review-created.ts (1)
13-13: Version bump only — LGTMNo logic changes. Source continues to dedupe by unique id and returns typed Review[] via listReviews.
components/google_my_business/actions/create-post/create-post.ts (1)
15-15: Version bump only — LGTMNo functional alterations to post creation flow.
components/google_my_business/sources/new-post-created/new-post-created.ts (1)
13-13: Version bump only — LGTMNo functional changes to event emission or summarization.
components/google_my_business/common/requestParams.ts (1)
54-56: LGTM:GetReviewParamsshape is correct and consistent with usageExtends
AccountLocationand adds the expectedreviewidentifier.components/google_my_business/actions/list-posts/list-posts.ts (1)
12-12: Version bump only — looks goodNo functional changes here; version increment aligns with app updates.
components/google_my_business/actions/list-all-reviews/list-all-reviews.ts (2)
21-29: Props wiring for dependent location looks goodLeveraging
propDefinitionwith the account-scoped resolver forlocationis consistent with other components.
31-47: No defensive guard needed:listReviewsreturns an array
Verified that incomponents/google_my_business/app.ts:145the methodasync listReviews({ account, location }: ListReviewsParams): Promise<Review[]> { … }returns a
Review[]. Usingresponse.lengthand returningresponseis correct.Likely an incorrect or invalid review comment.
components/google_my_business/sources/new-review-created-multiple-locations/new-review-created-multiple-locations.ts (3)
32-36: Deploy hook is appropriate for initial backfillCalling
getAndProcessData()on deploy aligns with the source pattern and ensures an initial run.
54-60: Summary generation looks goodConcise, readable summary with sensible truncation for long comments.
38-53: The search didn’t reveal aBatchGetReviewsParamsdefinition or how additional params are merged into the HTTP request. To be safe, please manually verify that:
- The
BatchGetReviewsParamsinterface actually allowsorderByandpageSize(or arbitrary query/body fields) under...args.- The HTTP body sent by
batchGetReviewsputs these fields in the correct place (e.g. underdata).- The Google My Business batchGetReviews endpoint supports
orderByandpageSizeparameters.Once confirmed, you can apply the refactor below; otherwise you may need to adjust/remove the
orderBy/pageSizeadditions.Suggested refactor
async getItems(): Promise<Review[]> { const { account, locationNames } = this; + const toFullName = (name: string) => + name.startsWith("accounts/") ? name : `accounts/${account}/locations/${name}`; - const params: BatchGetReviewsParams = { - account, - data: { - locationNames: locationNames?.map((locationName: string) => `accounts/${account}/locations/${locationName}`), - }, - }; + const params: BatchGetReviewsParams = { + account, + data: { + locationNames: locationNames?.map(toFullName) ?? [], + // Fetch newest only—remove or adjust pageSize if you need multiple reviews + orderBy: "updateTime desc", + pageSize: 1, + }, + }; const response: BatchGetReviewsResponse = await this.app.batchGetReviews(params); - return response?.locationReviews?.map((item) => item.review); + // Always return an array and flatten nested reviews + return ( + response.locationReviews?.flatMap((lr) => + lr.reviews ?? (lr.review ? [lr.review] : []) + ) ?? [] + ); },Please confirm that
orderByandpageSizeare accepted by both the params type and the My Business API before merging.
| export interface BatchGetReviewsResponse { | ||
| locationReviews: { | ||
| review: Review | ||
| }[]; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Response shape likely needs reviews: Review[] (not singular), and optional fields
The Google Business Profile batch endpoint typically returns multiple reviews per location. Current typing (review: Review) risks runtime issues when mapping in consumers and may drop reviews. Consider supporting both shapes or aligning to reviews: Review[]. Also add trailing semicolons for consistency.
-export interface BatchGetReviewsResponse {
- locationReviews: {
- review: Review
- }[];
-}
+export interface BatchGetReviewsResponse {
+ locationReviews: Array<{
+ // Fully-qualified location name, if returned
+ locationName?: string;
+ // Some implementations may return a single review
+ review?: Review;
+ // Prefer this if available: multiple reviews per location
+ reviews?: Review[];
+ // Pagination token per location, if applicable
+ nextPageToken?: string;
+ }>;
+}If you want to confirm the official schema first:
🌐 Web query:
What is the response schema of the Google Business Profile API batchGetReviews endpoint? Does it return a list `reviews` per location, and what fields are present under `locationReviews`?
💡 Result:
The response schema of the Google Business Profile API batchGetReviews endpoint consists of a top-level object containing a list called locationReviews, with each element representing reviews for a specific location. Each locationReview contains the location's identifier and a single review object (not a list), with all standard review fields present.
Key structure and fields:
-
Top-level fields in response:
locationReviews: An array of objects, each corresponding to a location and its associated review.nextPageToken: A string for pagination, present if more results are available[1][4][5].
-
Fields under
locationReviews:name: The location resource name (string), e.g.,"accounts/123/locations/456".review: An object containing the review data for the location[1].
Example response schema (JSON representation):
{
"locationReviews": [
{
"name": "accounts/123/locations/456",
"review": {
"reviewId": "string",
"comment": "string",
"reviewer": { /* reviewer info */ },
"starRating": "INTEGER",
"createTime": "timestamp",
"reviewReply": {
"comment": "string",
"updateTime": "timestamp"
}
// ...other review fields
}
}
// ...more locationReview objects
],
"nextPageToken": "string"
}Important details:
locationReviewsdoes not return a list of reviews per location. Instead, each entry inlocationReviewsrepresents a single review for a location. When requesting reviews for multiple locations, the endpoint returns a flattened list of individual reviews, with each including information about its associated location. You do not get a grouped list like{"location": ..., "reviews": [...]}[1][4].- The fields under
reviewmirror those available in the standard Review object (seeaccounts.locations.reviews.listor.get), including, but not limited to:reviewIdcommentreviewerstarRatingcreateTimereviewReply(optional, may be missing for some reviews)[4][1][3]
Summary Table
| Field | Type | Description |
|---|---|---|
| locationReviews | Array | Each item holds a location and a single review for that location |
| └─ name | String | Resource name of the location |
| └─ review | Object | The review data (reviewId, comment, reviewer, starRating, etc.) |
| nextPageToken | String (optional) | Used for pagination; not present if there are no more reviews |
In summary:
- The
batchGetReviewsresponse does not return a list of reviews per location. - Instead, it returns a flat list of
locationReviews, each with one review and the associated location name[1][4][5]. - The fields under
locationReviewsarenameandreview, withreviewcontaining all standard review data fields.
This design allows you to efficiently process reviews across multiple locations in one API call, but grouping reviews by location must be handled client-side if needed[1][4].
Citations:
- 1: https://developers.google.com/my-business/reference/rest/v4/accounts.locations/batchGetReviews
- 2: https://wpreviewslider.com/how-to-maximize-the-use-of-the-google-reviews-apis-for-business-reviews/
- 3: https://support.google.com/business/thread/21496556/with-batchgetreviews-method-from-gmb-api-the-reviewreply-information-is-missing-for-some-reviews?hl=en
- 4: https://developers.google.com/my-business/content/review-data
- 5: https://elfsight.com/blog/how-to-work-with-gmb-reviews-api/
- 6: https://pipedream.com/apps/google-my-business
- 7: https://serpapi.com/google-maps-reviews-api
- 8: https://localsearchforum.com/threads/scraping-google-reviews-api.47052/
- 9: https://www.youtube.com/watch?v=FXEgOPdPPoU
- 10: https://localsearchforum.com/threads/how-can-i-get-access-to-the-api.59795/
Align BatchGetReviewsResponse with actual API schema
The batchGetReviews endpoint returns a flat list of location reviews—each entry has a single review plus the location’s resource name—and an optional top-level nextPageToken. There is no reviews: Review[] array per location.
Please update your interface accordingly:
• File: components/google_my_business/common/responseSchemas.ts
• Replace existing definition with:
export interface BatchGetReviewsResponse {
/** All returned reviews, one per location */
locationReviews: Array<{
/** Resource name of the location, e.g. "accounts/123/locations/456" */
name: string;
/** The review data for this location */
review: Review;
}>;
/** Pagination token, if more reviews remain */
nextPageToken?: string;
}• Add trailing semicolons for consistency.
• Remove any reviews?: Review[] fields—those are not part of this endpoint’s response.
🤖 Prompt for AI Agents
In components/google_my_business/common/responseSchemas.ts around lines 26 to
30, the BatchGetReviewsResponse shape is incorrect: replace the current
per-location structure with a flat locationReviews array where each item
includes name: string and review: Review, add an optional top-level
nextPageToken?: string, remove any per-location reviews?: Review[] fields, and
ensure trailing semicolons are added to the interface members for consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🔭 Outside diff range comments (1)
components/google_my_business/sources/common.ts (1)
54-54: Type fix: allow null from getLastRun()getLastRun() returns Date | null, but lastRun is typed as Date. This can fail type-checking and obscures nullability.
Apply this diff:
- const lastRun: Date = this.getLastRun(); + const lastRun: Date | null = this.getLastRun();
🧹 Nitpick comments (1)
components/google_my_business/sources/common.ts (1)
58-60: Avoid duplicate emissions across runs: use strict '>' and compare Dates via getTime()Relational comparison against Date objects with >= can re-emit items created exactly at the lastRun boundary. Comparing numeric timestamps with a strict greater-than avoids duplicates and is clearer.
Apply this diff:
- ? items?.filter(({ createTime }) => new Date(createTime) >= lastRun) + ? items?.filter(({ createTime }) => new Date(createTime).getTime() > lastRun.getTime())
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (2)
components/google_my_business/sources/common.ts(1 hunks)components/google_my_business/sources/new-review-created-multiple-locations/new-review-created-multiple-locations.ts(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- components/google_my_business/sources/new-review-created-multiple-locations/new-review-created-multiple-locations.ts
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Lint Code Base
- GitHub Check: Publish TypeScript components
- GitHub Check: Verify TypeScript components
Closes #17821
Summary by CodeRabbit
New Features
Bug Fixes
Chores