Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export default defineAction({
key: "google_my_business-create-post",
name: "Create Post",
description: `Create a new local post associated with a location. [See the documentation](${DOCS_LINK})`,
version: "0.0.2",
version: "0.0.3",
type: "action",
props: {
app,
Expand Down Expand Up @@ -95,7 +95,8 @@ export default defineAction({
? JSON.parse(obj)
: obj;
} catch (err) {
throw new ConfigurationError(`**Invalid JSON string** for object prop: "${obj}"`);
throw new ConfigurationError(`**Invalid JSON string** for object prop: "${obj}"
Error: ${err}`);
}
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default defineAction({
key: "google_my_business-create-update-reply-to-review",
name: "Create or Update Reply to Review",
description: `Create or update a reply to the specified review. [See the documentation](${DOCS_LINK})`,
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
app,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import { defineAction } from "@pipedream/types";
import app from "../../app/google_my_business.app";
import { BatchGetReviewsParams } from "../../common/requestParams";

const DOCS_LINK = "https://developers.google.com/my-business/content/review-data#get_reviews_from_multiple_locations";

export default defineAction({
key: "google_my_business-get-reviews-multiple-locations",
name: "Get Reviews from Multiple Locations",
description: `Get reviews from multiple locations at once. [See the documentation](${DOCS_LINK})`,
version: "0.0.1",
type: "action",
props: {
app,
account: {
propDefinition: [
app,
"account",
],
},
locationNames: {
propDefinition: [
app,
"location",
({ account }: { account: string; }) => ({
account,
}),
],
type: "string[]",
label: "Location Names",
description: "One or more locations to get reviews from",
},
pageSize: {
type: "integer",
label: "Page Size",
description: "The number of reviews to return per location (max 50)",
optional: true,
default: 50,
min: 1,
max: 50,
},
orderBy: {
type: "string",
label: "Order By",
description: "How to order the reviews: by createTime or updateTime, and ascending or descending",
optional: true,
options: [
"createTime desc",
"createTime asc",
"updateTime desc",
"updateTime asc",
],
},
ignoreRatingOnlyReviews: {
type: "boolean",
label: "Ignore Rating Only Reviews",
description: "If true, only return reviews that have textual content",
optional: true,
default: false,
},
},
async run({ $ }) {
const {
account, locationNames, pageSize, orderBy, ignoreRatingOnlyReviews,
} = this;

const params: BatchGetReviewsParams = {
$,
account,
data: {
locationNames: locationNames?.map((locationName: string) => `accounts/${account}/locations/${locationName}`),
pageSize,
orderBy,
ignoreRatingOnlyReviews,
},
};

const response = await this.app.batchGetReviews(params);

$.export("$summary", `Successfully retrieved reviews from ${locationNames.length} locations`);

return response;
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { defineAction } from "@pipedream/types";
import app from "../../app/google_my_business.app";
import { GetReviewParams } from "../../common/requestParams";

const DOCS_LINK = "https://developers.google.com/my-business/content/review-data#get_a_specific_review";

export default defineAction({
key: "google_my_business-get-specific-review",
name: "Get a Specific Review",
description: `Return a specific review by name. [See the documentation](${DOCS_LINK})`,
version: "0.0.1",
type: "action",
props: {
app,
account: {
propDefinition: [
app,
"account",
],
},
location: {
propDefinition: [
app,
"location",
({ account }: { account: string; }) => ({
account,
}),
],
},
review: {
propDefinition: [
app,
"review",
({
account, location,
}: Record<string, string>) => ({
account,
location,
}),
],
},
},
async run({ $ }) {
const {
account, location, review,
} = this;

const params: GetReviewParams = {
$,
account,
location,
review,
};

const response = await this.app.getReview(params);

$.export("$summary", `Successfully retrieved review: ${review}`);

return response;
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { defineAction } from "@pipedream/types";
import app from "../../app/google_my_business.app";
import { ListReviewsParams } from "../../common/requestParams";

const DOCS_LINK = "https://developers.google.com/my-business/content/review-data#list_all_reviews";

export default defineAction({
key: "google_my_business-list-all-reviews",
name: "List All Reviews",
description: `List all reviews of a location to audit reviews in bulk. [See the documentation](${DOCS_LINK})`,
version: "0.0.1",
type: "action",
props: {
app,
account: {
propDefinition: [
app,
"account",
],
},
location: {
propDefinition: [
app,
"location",
({ account }: { account: string; }) => ({
account,
}),
],
},
},
async run({ $ }) {
const {
account, location,
} = this;

const params: ListReviewsParams = {
$,
account,
location,
};

const response = await this.app.listReviews(params);

$.export("$summary", `Successfully listed ${response.length} reviews`);

return response;
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export default defineAction({
key: "google_my_business-list-posts",
name: "List Posts",
description: `List local posts associated with a location. [See the documentation](${DOCS_LINK})`,
version: "0.0.1",
version: "0.0.2",
type: "action",
props: {
app,
Expand Down
19 changes: 18 additions & 1 deletion components/google_my_business/app/google_my_business.app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { defineApp } from "@pipedream/types";
import { axios } from "@pipedream/platform";
import {
CreatePostParams,
HttpRequestParams, ListPostsParams, ListReviewsParams, PaginatedRequestParams, UpdateReplyParams,
HttpRequestParams, ListPostsParams, ListReviewsParams, PaginatedRequestParams, UpdateReplyParams, GetReviewParams, BatchGetReviewsParams,
} from "../common/requestParams";
import {
Account, LocalPost, Location, Review,
Expand Down Expand Up @@ -187,5 +187,22 @@ export default defineApp({
...args,
});
},
async getReview({
account, location, review, ...args
}: GetReviewParams): Promise<Review> {
return this._httpRequest({
url: `https://mybusiness.googleapis.com/v4/accounts/${account}/locations/${location}/reviews/${review}`,
...args,
});
},
async batchGetReviews({
account, ...args
}: BatchGetReviewsParams): Promise<object> {
return this._httpRequest({
method: "POST",
url: `https://mybusiness.googleapis.com/v4/accounts/${account}/locations:batchGetReviews`,
...args,
});
},
},
});
15 changes: 15 additions & 0 deletions components/google_my_business/common/requestParams.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,18 @@ export interface UpdateReplyParams extends PdAxiosRequest, AccountLocation {
comment: string;
};
}

export interface GetReviewParams extends PdAxiosRequest, AccountLocation {
review: string;
}

export interface BatchGetReviewsParams extends PdAxiosRequest {
account: string;
data: {
locationNames: string[];
pageSize?: number;
pageToken?: string;
orderBy?: string;
ignoreRatingOnlyReviews?: boolean;
};
}
6 changes: 6 additions & 0 deletions components/google_my_business/common/responseSchemas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,9 @@ export interface Review extends EntityWithCreateTime {
export interface LocalPost extends EntityWithCreateTime {
summary: string;
}

export interface BatchGetReviewsResponse {
locationReviews: {
review: Review
}[];
}
Comment on lines +26 to +30
Copy link
Contributor

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:

  • locationReviews does not return a list of reviews per location. Instead, each entry in locationReviews represents 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 review mirror those available in the standard Review object (see accounts.locations.reviews.list or .get), including, but not limited to:
    • reviewId
    • comment
    • reviewer
    • starRating
    • createTime
    • reviewReply (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 batchGetReviews response 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 locationReviews are name and review, with review containing 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:


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.

2 changes: 1 addition & 1 deletion components/google_my_business/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@pipedream/google_my_business",
"version": "0.1.4",
"version": "0.2.0",
"description": "Pipedream Google My Business Components",
"main": "dist/app/google_my_business.app.mjs",
"keywords": [
Expand Down
6 changes: 3 additions & 3 deletions components/google_my_business/sources/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ export default {
const items: EntityWithCreateTime[] = await this.getItems();
this.setLastRun(currentRun);

const filteredItems = lastRun
? items.filter(({ createTime }) => new Date(createTime) >= lastRun)
: items.slice(-10);
const filteredItems = (lastRun
? items?.filter(({ createTime }) => new Date(createTime) >= lastRun)
: items?.slice(-10)) ?? [];

filteredItems.reverse().forEach((item) => {
this.$emit(item, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default defineSource({
key: "google_my_business-new-post-created",
name: "New Post Created",
description: `Emit new event for each new local post on a location [See the documentation](${DOCS_LINK})`,
version: "0.0.3",
version: "0.0.4",
type: "source",
dedupe: "unique",
methods: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { defineSource } from "@pipedream/types";
import { BatchGetReviewsParams } from "../../common/requestParams";
import {
BatchGetReviewsResponse, Review,
} from "../../common/responseSchemas";
import app from "../../app/google_my_business.app";
import common from "../common";

const DOCS_LINK = "https://developers.google.com/my-business/content/review-data#get_reviews_from_multiple_locations";

export default defineSource({
...common,
key: "google_my_business-new-review-created-multiple-locations",
name: "New Review Created (Multiple Locations)",
description: `Emit new event for each new review on any of the selected locations [See the documentation](${DOCS_LINK})`,
version: "0.0.1",
type: "source",
dedupe: "unique",
props: {
...common.props,
location: {
propDefinition: [
app,
"location",
({ account }: { account: string; }) => ({
account,
}),
],
type: "string[]",
label: "Location Names",
description: "One or more locations to monitor for new reviews",
},
},
hooks: {
async deploy() {
await this.getAndProcessData();
},
},
methods: {
...common.methods,
async getItems(): Promise<Review[]> {
const {
account, location,
} = this;

const params: BatchGetReviewsParams = {
account,
data: {
locationNames: location?.map((locationName: string) => `accounts/${account}/locations/${locationName}`),
},
};

const response: BatchGetReviewsResponse = await this.app.batchGetReviews(params);

return response?.locationReviews?.map((item) => item.review);
},
getSummary({ comment }: Review) {
return `New Review${comment
? `: "${comment.length > 50
? comment.slice(0, 45) + "[...]"
: comment}"`
: ""}`;
},
},
});
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default defineSource({
key: "google_my_business-new-review-created",
name: "New Review Created",
description: `Emit new event for each new review on a location [See the documentation](${DOCS_LINK})`,
version: "0.0.3",
version: "0.0.4",
type: "source",
dedupe: "unique",
methods: {
Expand Down
Loading
Loading