Google ads script, AdsApp.adGroups().get() returning empty - google-ads-api

I am developing a google ads script to run and create negative keywords, i get the performance using an SQLreport and when i try to create a negative keyword it does not work because when i try to return existing adgroups and initialize them, i get an empty result.
var adGroups = AdsApp.adGroups().get();
Logger.log('Total adGroups found : ' + adGroups.totalNumEntities());
This returns: Total AdGroups found : 0 -> but i have multiple running ads/adgroups in that sub-account.

because i was using google shopping i should have used: AdsApp.shoppingAdGroups()

Related

Internal Error in Google Sheets Custom Function with Multiple Input & Output Values - Change to use Range Formula

I have a Google Sheets table with a custom function. I have made a sanitized and reduced version of it here:
Google Sheet with Custom Function (CF)
The more rows I have in one tab, the more often I get the error:
"Error Internal error while executing the custom function."
Doing some research helped me to come to the conclusion that this issue is probably because the custom function is not used as a range formula as it is suggested here:
Optimizing Custom Functions
The custom function looks something like this:
function fifo(datesA, assetQtysA, transVolumesA, minHoldTime) {
//console.log("Original values: " + createCM({datesA, assetQtysA, transVolumesA, minHoldTime}));
var dates = [];
dates = Array.isArray(datesA) ? datesA : [datesA];
var assetQtys = [];
assetQtys = Array.isArray(assetQtysA) ? assetQtysA : [assetQtysA];
var transVolumes = [];
transVolumes = Array.isArray(transVolumesA) ? transVolumesA : [transVolumesA];
if (transVolumes.length === 0 || assetQtys.length === 0 || dates.length === 0) {
throw new Error('The transaction volumes, the asset quantities and the dates must each have at least one element!');
}
if (transVolumes.length !== assetQtys.length || transVolumes.length !== dates.length) {
throw new Error('The total transaction values, the asset quantities and dates must have the same amount of elements!');
}
if (assetQtys[0] < 0) {
throw new Error('The first transaction needs be a BUY transaction.');
}
//Something happening here ;-)
return [return_1, return_2, return_3, return_4, return_5, return_6];
Sorry, I'm not comfortable sharing the entire source code. But I hope you are able to understand.
So I'm trying to apply the range strategy (from the link above) on my special case, but have failed so far.
I have tried to apply this to the code, but I can't find my way out of multiple errors. I guess I'm on the wrong path here.
Anyone know how to manage this?
At least I hope after applying the range strategy the internal error message will disappear.
Many thanks for your help.

Importxml() returned "empty cells" or "formula parse error"

I tried Importhtml ("https://nepsealpha.com/investment-calandar/dividend","table",) and then Importxml("https://nepsealpha.com/investment-calandar/dividend",xpath). I found out xpath from "selectorgadget" extension of googlechrome, but still couldn't import it. It shows either "empty content" or formula parse error".
You can retrieve quite all the informations this way
=importxml(url,"//div/#data-page")
and then parse the json.
By script : =getData("https://nepsealpha.com/investment-calandar/dividend")
function getData(url) {
var from='data-page="'
var to='"></div></body>'
var jsonString = UrlFetchApp.fetch(url).getContentText().split(from)[1].split(to)[0].replace(/"/g,'"')
var json = JSON.parse(jsonString).props.today_prices_summary.top_volume
var headers = Object.keys(json[0]);
return ([headers, ...json.map(obj => headers.map(header => obj[header]))]);
}
edit
to update periodically, add this script
function update(){
var chk = SpreadsheetApp.getActiveSpreadsheet().getSheets()[0].getRange('A1')
chk.setValue(!chk.getValue())
}
put a trigger as you wish on the update function and change as follows
=getData("https://nepsealpha.com/investment-calandar/dividend",$A$1)
I know that's not the answer you want to see.
It's impossible to get any content from this website using IMPORTXML or other tools included in Google Sheets.
It's generated using Javascript. Once Javascript is disabled no content is displayed:
It's done on purpose. Financial companies pay for live stock data and they don't want to share it with us for free.
So the site is protected against tools like importxml.

How to find the right xpath for Google sheets?

I would like to scrape data from a page, but cannot figure out the right xpath for Google sheets. I would like to extract the number 202 from https://www.belvilla.nl/zoeken/?land=nl&rgo=frie (on top of the page, "202
vakantiehuizen gevonden in Friesland")
If I take the xpath, I get: //*[#id="result-container-items"]/div[1]/div/div/div[1]/div[1]/div[1]/strong
In Google sheets I have tried =IMPORTXML(A1;"//*[#id="result-container-items"]/div[1]/div/div/div[1]/div[1]/div[1]/strong)") and some others like =IMPORTXML(A1;"//div[#class='search-numbers']"), but none of them are working. For the last one I get an error with 'Resource with URL content has exceeded the size limit.' but I'm guessing my xpath is wrong.
Can anyone help me out? Thanks!
IMPORTXML has its limitations especially on JS elements. However, if scripting is an option, try using UrlFetchApp.fetch() in Google Apps Script.
Code:
function fetchUrl(url) {
var html = UrlFetchApp.fetch(url).getContentText();
// startString and endString must be unique or at least the first result
// enclosing the result we want
var startString = 'search-result-div" ';
var endString = 'alternate-dates-filter-bar';
var startIndex = html.search(startString);
var endIndex = html.search(endString);
// regex for numbers and text content
var numbers = /strong>([^<]+)<\/strong/;
var text = /span>([^<]+)<\/span/;
// clean content then combine matches of numbers and text
var content = html.substring(startIndex, endIndex).replace(/\s\s+/g, ' ');
var result = numbers.exec(content)[1] + ' ' + text.exec(content)[1];
return result.trim();
}
Output:
Note:
Code above is specific to what you are fetching. You will need to update the script processing of the response if you want anything else.
You can reuse this on other url and will fetch the similar value located on your wanted xpath in your post.
This doesn't make use of the xpath.
google sheets do not support the scraping of JavaScript elements. you can check this if you disable JS for a given URL and you will be left with content you could import. in your case, this cant be achieved with IMPORTXML:

AdWords PLACEMENT_PERFORMANCE_REPORT not pulling URLs

This should be extremely simple but for some reason it doesn't seem to work. I'm trying to pull the URLs of display placements using the DISPLAY_PERFORMANCE_REPORT but instead of URLs it's just returning "--".
The code I'm using is:
var report = AdWordsApp.report(
"SELECT CampaignName, Clicks, FinalAppUrls, FinalUrls " +
"FROM PLACEMENT_PERFORMANCE_REPORT " +
"WHERE Clicks > 0 " +
"DURING LAST_30_DAYS");
var rows = report.rows();
while (rows.hasNext()) {
var row = rows.next();
var url = row["FinalUrls"];
Logger.log(url);
}
I've tried logging the CampaignName and clicks and they're working as expected, so can't understand what the issue is here. The only thing I can think of is that in the reference guide it says:
List of final URLs of the main object of this row. UrlList elements
are returned in JSON list format
I'm not entirely sure what JSON list format is, but when I log the typeof url it says it's a string, so thought it shouldn't be an issue.
The FinalAppUrls and FinalUrls list the target URLs that you set on the individual managed placements.
If you're interested in the URL (domain, rather) of the placement itself, you'll have to request either the Criteria or the DisplayName field in your report——they both contain the domain of the placement.

Can you write a Google Sheets function that draws something?

Is it possible to write your own custom function in google sheets script that returns a drawn image, similar to how the SPARKLINE function works, except I want to make one that draws a pie chart instead.
I do not want to use Insert > Chart... > Pie Chart because that creates a floating chart on top of the spreadsheet. I would like to be able to write my own function that would return a pie chart that is embedded within the cell that the function is entered in, just like you can do with columns, bars, and line charts using sparkline.
How about following idea? This sample script embeds a chart to a cell using custom function on Spreadsheet. I think that this method is one of various ideas.
Problems :
When you want to create a chart and embed it to a cell using custom functions, you notice that insertChart() cannot be used. There are some limitations for using custom functions. But insertChart() creates floating charts. So in order to embed a chart to a cell, the function =IMAGE() is suitable for this situation. Here, setFormula() for setting =IMAGE() and DriveApp.createFile() for creating images from charts also cannot be used for custom functions.
Solution :
In order to avoid these limitations, I used Web Apps.
To use this sample script, please deploy Web Apps as follows.
On the Script Editor,
File
-> Manage Versions
-> Save New Version
Publish
-> Deploy as Web App
-> At Execute the app as, select "your account"
-> At Who has access to the app, select "Anyone, even anonymous"
-> Click "Deploy"
-> Copy "Current web app URL"
-> Click "OK"
When it deploys Web Apps, the approval required authorization can be done, simultaneously.
Sample Script :
Please copy and paste this script to a bound script of spreadsheet.
var folderId = "### Folder ID ###"; // This is a folder to save images.
var webappsurl = "https://script.google.com/macros/s/######/exec"; // Here, please put "Current web app URL".
function embedChart(range) {
var ac = SpreadsheetApp.getActiveSheet().getActiveCell();
var q1 = "?datarange=" + range;
var q2 = "&row=" + ac.getRow();
var q3 = "&col=" + ac.getColumn();
var url = webappsurl + q1 + q2 + q3;
UrlFetchApp.fetch(url);
}
function doGet(e) {
var sheet = SpreadsheetApp.getActiveSheet();
var chart = sheet.newChart()
.setChartType(Charts.ChartType.PIE)
.addRange(sheet.getRange(e.parameters.datarange))
.setOption('height', 280)
.setOption('width', 480)
.setOption('title', 'Sample chart')
.build();
var file = DriveApp.getFolderById(folderId).createFile(
chart.getAs('image/png').setName("chart_image.png")
);
file.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.VIEW);
sheet.getRange(e.parameters.row, e.parameters.col).setFormula(
'=IMAGE("' + "http://drive.google.com/uc?id=" + file.getId() + '")'
);
}
Flow of Script :
embedChart()
Input =embedChart("a2:a6") in cell B7.
Using fetch(), sends data of a2:a6 and the inputted coordinate to doGet().
doGet()
Using doGet(), get the data.
Creates a chart using inputted range a2:a6. (in this case, creates a pie chart)
Saves a chart as an image. (in this case, saves as PNG)
Updates a permission of the image file to use for =IMAGE().
Embeds the image using =IMAGE() which was imported by setFormula().
Result :
By inputting =embedChart("a2:a6") in cell B7 as a custom function, following result can be obtained.
Note :
When the custom function embedChart() is used, loading time is about 40 seconds. (I don't know whether this occurs at only my environment.)
Permissions of the created image are ANYONE_WITH_LINK, VIEW.
embedChart() is overwritten by =IMAGE(). So when the spreadsheet is reopened, the response of =IMAGE() is much faster than that of embedChart().
If I misunderstand your question, I'm sorry.

Resources