How to Resolve Incompatibility Issue between PipeDream's ES Module and CommonJS-based Google Ads API?

This topic was automatically generated from Slack. You can find the original thread here.

trying to call the Google Ads API in a step, but keep running into an issue:

9/10/2023, 3:12:35 PM
TypeError: GoogleAdsClient is not a constructor
at run (file:///tmp/pdg/dist/code/0413bd4091dffd495be0fade76a238e8253cce5fc737be3a777312337b8c7f1a/index.mjs:10:18)
at file:///tmp/pdg/dist/code/0413bd4091dffd495be0fade76a238e8253cce5fc737be3a777312337b8c7f1a/index.mjs:57:1
at ModuleJob.run (node:internal/modules/esm/module_job:194:25)

The issue suggests that the GoogleAdsClient object is not being correctly imported and recognized as a constructor. This could be an incompatibility issue between PipeDream’s ES module system and the CommonJS-based google-ads-node package.

Any recommendations on how to make this work?

It seems like you’re facing an issue with the module format when trying to use the google-ads-node package. Pipedream uses ES modules, and the package might be using CommonJS format. To resolve this issue, you can try the following: 1. Convert the require statement to an import statement, if you’re using require. For example, change: const { GoogleAdsClient } = require("google-ads-node"); to: import { GoogleAdsClient } from "google-ads-node"; 2. If the import syntax doesn’t work, you can try separating your imports into different steps. Use only CommonJS require statements in one step, and only ESM import statements in another. If you still face issues, please let me know and provide more details about your code, so I can help you further.

how would you structure this to work in PipeDream?

private void runExample(
    GoogleAdsClient googleAdsClient,
    long customerId,
    long languageId,
    List<Long> locationIds,
    List<String> keywords,
    @Nullable String pageUrl) {
  try (KeywordPlanIdeaServiceClient keywordPlanServiceClient =
      googleAdsClient.getLatestVersion().createKeywordPlanIdeaServiceClient()) {
    GenerateKeywordIdeasRequest.Builder requestBuilder =
        GenerateKeywordIdeasRequest.newBuilder()
            .setCustomerId(Long.toString(customerId))
            // Sets the language resource using the provided language ID.
            .setLanguage(ResourceNames.languageConstant(languageId))
            // Sets the network. To restrict to only Google Search, change the parameter below to
            // KeywordPlanNetwork.GOOGLE_SEARCH.
            .setKeywordPlanNetwork(KeywordPlanNetwork.GOOGLE_SEARCH_AND_PARTNERS);

    // Adds the resource name of each location ID to the request.
    for (Long locationId : locationIds) {
      requestBuilder.addGeoTargetConstants(ResourceNames.geoTargetConstant(locationId));
    }

    // Makes sure that keywords and/or page URL were specified. The request must have exactly one
    // of urlSeed, keywordSeed, or keywordAndUrlSeed set.
    if (keywords.isEmpty() && pageUrl == null) {
      throw new IllegalArgumentException(
          "At least one of keywords or page URL is required, but neither was specified.");
    }

    if (keywords.isEmpty()) {
      // Only page URL was specified, so use a UrlSeed.
      requestBuilder.getUrlSeedBuilder().setUrl(pageUrl);
    } else if (pageUrl == null) {
      // Only keywords were specified, so use a KeywordSeed.
      requestBuilder.getKeywordSeedBuilder().addAllKeywords(keywords);
    } else {
      // Both page URL and keywords were specified, so use a KeywordAndUrlSeed.
      requestBuilder.getKeywordAndUrlSeedBuilder().setUrl(pageUrl).addAllKeywords(keywords);
    }

    // Sends the keyword ideas request.
    GenerateKeywordIdeasPagedResponse response =
        keywordPlanServiceClient.generateKeywordIdeas(requestBuilder.build());
    // Prints each result in the response.
    for (GenerateKeywordIdeaResult result : response.iterateAll()) {
      System.out.printf(
          "Keyword idea text '%s' has %d average monthly searches and '%s' competition.%n",
          result.getText(),
          result.getKeywordIdeaMetrics().getAvgMonthlySearches(),
          result.getKeywordIdeaMetrics().getCompetition());
    }
  }
}

To adapt the provided Java code to work in Pipedream, you’ll need to rewrite it in JavaScript and use the Google Ads API within a Pipedream component. Here’s a basic example of how you could structure the code: ```
import { axios } from “@pipedream/platform”; export default defineComponent({ props: { googleAdsClient: { type: “app”, app: “google_ads”, }, customerId: { type: “string”, label: “Customer ID”, }, languageId: { type: “string”, label: “Language ID”, }, locationIds: { type: “string[]”, label: “Location IDs”, }, keywords: { type: “string[]”, label: “Keywords”, }, pageUrl: { type: “string”, label: “Page URL”, optional: true, }, }, async run({ steps, $ }) { // You’ll need to use the Google Ads API here, which might require additional setup. // The example below is just a placeholder to show how you can structure the code. // Replace it with the actual API calls and logic from the provided Java code. const response = await axios($, { method: “GET”, url: “https://example.com/google-ads-api”, // Replace with the actual Google Ads API endpoint headers: { Authorization: Bearer ${this.googleAdsClient.$auth.oauth_access_token}, }, params: { customerId: this.customerId, languageId: this.languageId, locationIds: this.locationIds, keywords: this.keywords, pageUrl: this.pageUrl, }, }); // Process the response and return the desired data const results = response.data; // Replace with the actual response data processing return results; }, });

can you please rewrite this to use Google Ads REST API?

To rewrite the provided Java code to work with the Google Ads REST API in Pipedream, you’ll need to use JavaScript and make the necessary API calls within a Pipedream component. Here’s a basic example to get you started: ```
import { axios } from “@pipedream/platform”; export default defineComponent({ props: { googleAdsClient: { type: “app”, app: “google_ads”, }, customerId: { type: “string”, label: “Customer ID”, }, // Add other required props here }, async run({ steps, $ }) { // Replace the URL below with the actual Google Ads REST API endpoint const url = “https://googleads.googleapis.com/v10/customers/{customer_id}/campaigns”; // Replace with the correct endpoint const response = await axios($, { method: “GET”, url: url.replace(“{customer_id}”, this.customerId), headers: { Authorization: Bearer ${this.googleAdsClient.$auth.oauth_access_token}, “developer-token”: “YOUR_DEVELOPER_TOKEN”, // Replace with your developer token “login-customer-id”: “YOUR_LOGIN_CUSTOMER_ID”, // Replace with your login customer ID if required }, // Add any required parameters here }); // Process the response and return the desired data const results = response.data; // Replace with the actual response data processing return results; }, });

import { axios } from@pipedream/platform”;

export default defineComponent({
props: {
google_ads: {
type: “app”,
app: “google_ads”,
},
customerId: {
type: “string”,
label: “Customer ID”,
},
locationIds: {
type: “string[]”,
label: “Location IDs”,
},
languageId: {
type: “string”,
label: “Language ID”,
},
keywordTexts: {
type: “string[]”,
label: “Keyword Texts”,
},
pageUrl: {
type: “string”,
label: “Page URL”,
},
},
async run({ $ }) {
const url = ‘https://adwords.googleapis.com/api/adwords/v201809/KeywordPlanIdeaService/generate’;
const response = await axios($, {
method: ‘post’,
url,
data: {
customerId: this.customerId,
locationIds: this.locationIds,
languageId: this.languageId,
keywordTexts: this.keywordTexts,
pageUrl: this.pageUrl
},
headers: {
Authorization: Bearer ${**this**.google_ads.$auth.access_token}
}
});
return response;
},
});

Error:

steps.node{1}
debug{5}
status:
404
statusText:
Not Found
headers{9}config{12}data!DOCTYPE html
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
**{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}** > body{background:url(<//www.google.com/images/errors/robot.png>) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(<//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png>) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(<//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png>) no-repeat 0% 0%/100% 100%;-moz-border-image:url(<//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png>) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(<//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png>) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=<//www.google.com/>><span id=logo aria-label=Google></span></a>
<p><b>404.</b> <ins>That's an error.</ins>
<p>The requested URL <code>/api/adwords/v201809/KeywordPlanIdeaService/generate</code> was not found on this server. <ins>That's all we know.</ins>

It seems like you’re trying to make a request to the Google Ads API, but the URL you’re using is incorrect, which is causing the 404 error. The correct base URL for the Google Ads API is https://googleads.googleapis.com. Please update the URL in your code and refer to the Google Ads API documentation for the correct endpoint for your request.

I am still getting an error:

Error - Request failed with status code 404
“!DOCTYPE html\n\n \n <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">\n Error 404 (Not Found)!!1\n \n {margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px} > body{background:url(<//www.google.com/images/errors/robot.png>) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(<//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png>) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(<//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png>) no-repeat 0% 0%/100% 100%;-moz-border-image:url(<//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png>) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(<//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png>) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}\n \n <a href=<//www.google.com/>>\n

404. That’s an error.\n

The requested URL /v1/customers/9998828401/googleAds:search was not found on this server. That’s all we know.\n”
DETAILS

    at null.createError (/tmp/__pdg__/dist/code/063c55a4e5ebca21cd917214be56569db38fd75915c17acb1722ed2e32e8fe93/node_modules/.pnpm/axios@0.21.4/node_modules/axios/lib/core/createError.js:16:15)
    at null.settle (/tmp/__pdg__/dist/code/063c55a4e5ebca21cd917214be56569db38fd75915c17acb1722ed2e32e8fe93/node_modules/.pnpm/axios@0.21.4/node_modules/axios/lib/core/settle.js:17:12)
    at IncomingMessage.handleStreamEnd (/tmp/__pdg__/dist/code/063c55a4e5ebca21cd917214be56569db38fd75915c17acb1722ed2e32e8fe93/node_modules/.pnpm/axios@0.21.4/node_modules/axios/lib/adapters/http.js:269:11)
    at IncomingMessage.emit (node:events:526:35)
    at null.endReadableNT (node:internal/streams/readable:1359:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)

steps.node{1}
debug{5}

I apologize for the inconvenience. It seems like the endpoint you’re trying to access is not correct. To help you further, I need more information about the Google Ads API request you’re trying to make. Can you please provide more details about the API operation you want to perform? This will help me guide you to the correct endpoint and resolve the issue.

Code:

import { axios } from@pipedream/platform”;

export default defineComponent({
props: {
google_ads: {
type: “app”,
app: “google_ads”,
},
customerId: {
type: “string”,
label: “Customer ID”,
},
locationIds: {
type: “string[]”,
label: “Location IDs”,
},
languageId: {
type: “string”,
label: “Language ID”,
},
keywordTexts: {
type: “string[]”,
label: “Keyword Texts”,
},
pageUrl: {
type: “string”,
label: “Page URL”,
},
},
async run({ $ }) {
const url = https://googleads.googleapis.com/v1/customers/${**this**.customerId}/googleAds:search;
const query = test ; // Replace with the query you want to use

**const** response = **await** axios($, {
  method: 'post',
  url,
  data: {
    pageSize: 10,
    query
  },
  headers: {
    Authorization: `Bearer ${**this**.google_ads.$auth.access_token}`,
    "Content-Type": "application/json",
    "developer-token": "_fljZgxK5ofEFi54McNeqQ", _// Replace with your developer token_
  },
});
**return** response;

},
});

Error:

Error - Request failed with status code 404
“!DOCTYPE html\n\n \n <meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">\n Error 404 (Not Found)!!1\n \n {margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px} > body{background:url(<//www.google.com/images/errors/robot.png>) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(<//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png>) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(<//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png>) no-repeat 0% 0%/100% 100%;-moz-border-image:url(<//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png>) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(<//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png>) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}\n \n <a href=<//www.google.com/>>\n

404. That’s an error.\n

The requested URL /v1/customers/999-882-8401/googleAds:search was not found on this server. That’s all we know.\n”
DETAILS

    at null.createError (/tmp/__pdg__/dist/code/063c55a4e5ebca21cd917214be56569db38fd75915c17acb1722ed2e32e8fe93/node_modules/.pnpm/axios@0.21.4/node_modules/axios/lib/core/createError.js:16:15)
    at null.settle (/tmp/__pdg__/dist/code/063c55a4e5ebca21cd917214be56569db38fd75915c17acb1722ed2e32e8fe93/node_modules/.pnpm/axios@0.21.4/node_modules/axios/lib/core/settle.js:17:12)
    at IncomingMessage.handleStreamEnd (/tmp/__pdg__/dist/code/063c55a4e5ebca21cd917214be56569db38fd75915c17acb1722ed2e32e8fe93/node_modules/.pnpm/axios@0.21.4/node_modules/axios/lib/adapters/http.js:269:11)
    at IncomingMessage.emit (node:events:526:35)
    at null.endReadableNT (node:internal/streams/readable:1359:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21)

steps.node{1}
debug{5}

It looks like you’re getting a 404 error, which means the requested URL was not found on the server. The URL you’re using is https://googleads.googleapis.com/v1/customers/${this.customerId}/googleAds:search. Please double-check the Google Ads API documentation to make sure you’re using the correct endpoint. If you’re still having trouble, please visit https://pipedream.com/support for more support options.