diff --git a/docs/api_refs/blacklisted-entrypoints.json b/docs/api_refs/blacklisted-entrypoints.json
index ea3491ec2294..419d8800827d 100644
--- a/docs/api_refs/blacklisted-entrypoints.json
+++ b/docs/api_refs/blacklisted-entrypoints.json
@@ -7,6 +7,7 @@
"../../langchain/src/tools/connery.ts",
"../../langchain/src/tools/gmail.ts",
"../../langchain/src/tools/google_places.ts",
+ "../../langchain/src/tools/google_trends.ts",
"../../langchain/src/embeddings/bedrock.ts",
"../../langchain/src/embeddings/cloudflare_workersai.ts",
"../../langchain/src/embeddings/ollama.ts",
diff --git a/docs/core_docs/docs/integrations/tools/google_trends.mdx b/docs/core_docs/docs/integrations/tools/google_trends.mdx
new file mode 100644
index 000000000000..bbbdec5d70c0
--- /dev/null
+++ b/docs/core_docs/docs/integrations/tools/google_trends.mdx
@@ -0,0 +1,42 @@
+---
+hide_table_of_contents: true
+---
+
+import CodeBlock from "@theme/CodeBlock";
+
+# Google Trends Tool
+
+The Google Trends Tool allows your agent to utilize the Google Trends API from SerpApi to retrieve and analyze search interest data.
+This can be useful for understanding trending topics, regional search interest, and historical popularity of search terms.
+
+For API details see [here](https://serpapi.com/google-trends-api)
+
+SerpApi caches queries, so the first query will be slower while subsequent identical queries will be fast.
+Occasionally, related queries will not work while interest over time will be fine. You can check your query [here](https://serpapi.com/playground?engine=google_trends&q=monster&data_type=RELATED_QUERIES).
+
+## Setup
+
+To use this tool, you will need to configure access to the Google Trends API from SerpApi.
+
+Get an API key from [SerpApi](https://serpapi.com/users/sign_in)
+
+Then, set your API key as `process.env.SERPAPI_API_KEY` or pass it in as an `apiKey` constructor argument.
+
+## Usage
+
+import IntegrationInstallTooltip from "@mdx_components/integration_install_tooltip.mdx";
+
+
+
+```bash npm2yarn
+npm install @langchain/openai @langchain/community @langchain/core
+```
+
+import ToolExample from "@examples/tools/google_trends.ts";
+
+{ToolExample}
+
+## Related
+
+- Tool [conceptual guide](/docs/concepts/tools)
+- Tool [how-to guides](/docs/how_to/#tools)
diff --git a/examples/src/tools/google_trends.ts b/examples/src/tools/google_trends.ts
new file mode 100644
index 000000000000..25cf5f174ba3
--- /dev/null
+++ b/examples/src/tools/google_trends.ts
@@ -0,0 +1,9 @@
+import { SERPGoogleTrendsTool } from "@langchain/community/tools/google_trends";
+
+export async function run() {
+ const tool = new SERPGoogleTrendsTool();
+
+ const res = await tool.invoke("Monster");
+
+ console.log(res);
+}
diff --git a/libs/langchain-community/.gitignore b/libs/langchain-community/.gitignore
index 5064c1f14c79..8dc708cbe23e 100644
--- a/libs/langchain-community/.gitignore
+++ b/libs/langchain-community/.gitignore
@@ -70,6 +70,10 @@ tools/google_places.cjs
tools/google_places.js
tools/google_places.d.ts
tools/google_places.d.cts
+tools/google_trends.cjs
+tools/google_trends.js
+tools/google_trends.d.ts
+tools/google_trends.d.cts
tools/google_routes.cjs
tools/google_routes.js
tools/google_routes.d.ts
diff --git a/libs/langchain-community/langchain.config.js b/libs/langchain-community/langchain.config.js
index b0207b8612ab..547960384372 100644
--- a/libs/langchain-community/langchain.config.js
+++ b/libs/langchain-community/langchain.config.js
@@ -51,6 +51,7 @@ export const config = {
"tools/google_calendar": "tools/google_calendar/index",
"tools/google_custom_search": "tools/google_custom_search",
"tools/google_places": "tools/google_places",
+ "tools/google_trends": "tools/google_trends",
"tools/google_routes": "tools/google_routes",
"tools/ifttt": "tools/ifttt",
"tools/searchapi": "tools/searchapi",
diff --git a/libs/langchain-community/package.json b/libs/langchain-community/package.json
index 6cdbe97e2664..108a51c174ce 100644
--- a/libs/langchain-community/package.json
+++ b/libs/langchain-community/package.json
@@ -874,6 +874,15 @@
"import": "./tools/google_places.js",
"require": "./tools/google_places.cjs"
},
+ "./tools/google_trends": {
+ "types": {
+ "import": "./tools/google_trends.d.ts",
+ "require": "./tools/google_trends.d.cts",
+ "default": "./tools/google_trends.d.ts"
+ },
+ "import": "./tools/google_trends.js",
+ "require": "./tools/google_trends.cjs"
+ },
"./tools/google_routes": {
"types": {
"import": "./tools/google_routes.d.ts",
@@ -3191,6 +3200,10 @@
"tools/google_places.js",
"tools/google_places.d.ts",
"tools/google_places.d.cts",
+ "tools/google_trends.cjs",
+ "tools/google_trends.js",
+ "tools/google_trends.d.ts",
+ "tools/google_trends.d.cts",
"tools/google_routes.cjs",
"tools/google_routes.js",
"tools/google_routes.d.ts",
diff --git a/libs/langchain-community/src/tools/google_trends.ts b/libs/langchain-community/src/tools/google_trends.ts
new file mode 100644
index 000000000000..18f063e791e8
--- /dev/null
+++ b/libs/langchain-community/src/tools/google_trends.ts
@@ -0,0 +1,161 @@
+import { getEnvironmentVariable } from "@langchain/core/utils/env";
+import { Tool } from "@langchain/core/tools";
+
+/**
+ * Interfaces for the response from the SerpApi Google Trends API.
+ */
+interface TimelineValue {
+ query: string;
+ value: string;
+ extracted_value: number;
+}
+
+interface TimelineData {
+ date: string;
+ timestamp: string;
+ values: TimelineValue[];
+}
+
+/**
+ * Interface for parameters required by SERPGoogleTrendsTool class.
+ */
+export interface SERPGoogleTrendsToolParams {
+ apiKey?: string;
+}
+
+/**
+ * Tool that queries the Google Trends API. Uses default interest over time.
+ */
+export class SERPGoogleTrendsTool extends Tool {
+ static lc_name() {
+ return "SERPGoogleTrendsTool";
+ }
+
+ get lc_secrets(): { [key: string]: string } | undefined {
+ return {
+ apiKey: "SERPAPI_API_KEY",
+ };
+ }
+
+ name = "google_trends";
+
+ protected apiKey: string;
+
+ description = `A wrapper around Google Trends API. Useful for analyzing and retrieving trending search data based on keywords,
+ categories, or regions. Input should be a search query or specific parameters for trends analysis.`;
+
+ constructor(fields?: SERPGoogleTrendsToolParams) {
+ super(...arguments);
+ const apiKey = fields?.apiKey ?? getEnvironmentVariable("SERPAPI_API_KEY");
+ if (apiKey === undefined) {
+ throw new Error(
+ `Google Trends API key not set. You can set it as "SERPAPI_API_KEY" in your environment variables.`
+ );
+ }
+ this.apiKey = apiKey;
+ }
+
+ async _call(query: string): Promise {
+ /**
+ * Related queries only accepts one at a time, and multiple
+ * queries at once on interest over time (default) is effectively the same as
+ * each query one by one.
+ *
+ * SerpApi caches queries, so the first time will be slower
+ * and subsequent identical queries will be very fast.
+ */
+ if (query.split(",").length > 1) {
+ throw new Error("Please do one query at a time");
+ }
+ const serpapiApiKey = this.apiKey;
+ const params = new URLSearchParams({
+ engine: "google_trends",
+ api_key: serpapiApiKey,
+ q: query,
+ });
+
+ const res = await fetch(
+ `https://serpapi.com/search.json?${params.toString()}`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+
+ if (!res.ok) {
+ throw new Error(`Error fetching data from SerpAPI: ${res.statusText}`);
+ }
+
+ const clientDict = await res.json();
+ const totalResults = clientDict.interest_over_time?.timeline_data ?? [];
+
+ if (totalResults.length === 0) {
+ return "No good Trend Result was found";
+ }
+
+ const startDate = totalResults[0].date.split(" ");
+ const endDate = totalResults[totalResults.length - 1].date.split(" ");
+ const values = totalResults.map(
+ (result: TimelineData) => result.values[0].extracted_value
+ );
+ const minValue = Math.min(...values);
+ const maxValue = Math.max(...values);
+ const avgValue =
+ values.reduce((a: number, b: number) => a + b, 0) / values.length;
+ const percentageChange =
+ ((values[values.length - 1] - values[0]) / (values[0] || 1)) * 100;
+
+ const relatedParams = new URLSearchParams({
+ engine: "google_trends",
+ api_key: serpapiApiKey,
+ data_type: "RELATED_QUERIES",
+ q: query,
+ });
+
+ const relatedRes = await fetch(
+ `https://serpapi.com/search.json?${relatedParams.toString()}`,
+ {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ }
+ );
+
+ let rising = [];
+ let top = [];
+ if (!relatedRes.ok) {
+ // Sometimes related queries from SerpAPI will fail, but interest over time will be fine
+ console.error(
+ `Error fetching related queries from SerpAPI: ${relatedRes.statusText}`
+ );
+ } else {
+ const relatedDict = await relatedRes.json();
+ rising =
+ relatedDict.related_queries?.rising?.map(
+ (result: { query: string }) => result.query
+ ) ?? [];
+ top =
+ relatedDict.related_queries?.top?.map(
+ (result: { query: string }) => result.query
+ ) ?? [];
+ }
+
+ const doc = [
+ `Query: ${query}`,
+ `Date From: ${startDate[0]} ${startDate[1]}, ${startDate[2]}`,
+ `Date To: ${endDate[0]} ${endDate[1]} ${endDate[2]}`,
+ `Min Value: ${minValue}`,
+ `Max Value: ${maxValue}`,
+ `Average Value: ${avgValue}`,
+ `Percent Change: ${percentageChange.toFixed(2)}%`,
+ `Trend values: ${values.join(", ")}`,
+ `Rising Related Queries: ${rising.join(", ")}`,
+ `Top Related Queries: ${top.join(", ")}`,
+ ];
+
+ return doc.join("\n\n");
+ }
+}
diff --git a/libs/langchain-community/src/tools/tests/google_trends.int.test.ts b/libs/langchain-community/src/tools/tests/google_trends.int.test.ts
new file mode 100644
index 000000000000..49be189bd7ad
--- /dev/null
+++ b/libs/langchain-community/src/tools/tests/google_trends.int.test.ts
@@ -0,0 +1,34 @@
+import { expect, describe } from "@jest/globals";
+import { SERPGoogleTrendsTool } from "../google_trends.js";
+
+describe("SERPGoogleTrendsTool", () => {
+ test("should be setup with correct parameters", async () => {
+ const instance = new SERPGoogleTrendsTool();
+ expect(instance.name).toBe("google_trends");
+ });
+
+ test("SERPGoogleTrendsTool returns expected result for valid query", async () => {
+ const tool = new SERPGoogleTrendsTool();
+
+ const result = await tool._call("Coffee");
+
+ expect(result).toContain("Query: Coffee");
+ expect(result).toContain("Date From:");
+ expect(result).toContain("Date To:");
+ expect(result).toContain("Min Value:");
+ expect(result).toContain("Max Value:");
+ expect(result).toContain("Average Value:");
+ expect(result).toContain("Percent Change:");
+ expect(result).toContain("Trend values:");
+ expect(result).toContain("Rising Related Queries:");
+ expect(result).toContain("Top Related Queries:");
+ });
+
+ test("SERPGoogleTrendsTool returns 'No good Trend Result was found' for a non-existent query", async () => {
+ const tool = new SERPGoogleTrendsTool();
+
+ const result = await tool._call("earghajgpajrpgjaprgag");
+
+ expect(result).toBe("No good Trend Result was found");
+ });
+});