Advertisement
Guest User

Untitled

a guest
Feb 19th, 2018
294
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 25.57 KB | None | 0 0
  1. /*
  2. // Kurzanleitung:
  3. // 1. Den Code zwischen START bis ENDE kopieren
  4. // 2. Neues AdWords-Script in AdWords erstellen und den Code einfügen
  5. // 3. Die g_... Parameter anpassen
  6. // 4. Insb. reportFoundPhrases anpassen, um über markantem Text Landingpages zu identifizieren, die z.B. nicht mehr lieferbare Produkte anzeigen
  7. // 5. Speichern und testen
  8. // 6. Tipp: Zeitplan erstellen und z.B. täglich um 1 Uhr ausführen lassen
  9. // Siehe auch https://www.internet-marketing-inside.de/free-AdWords-Scripts.html
  10.  
  11.  
  12.  
  13. // START in Zwischenablage kopieren
  14.  
  15. // free LinkChecker AdWords-Script (https://www.internet-marketing-inside.de/AdWords-Scripts/linkchecker.html / Copyright data-inside GmbH)
  16. var g_sMailAddress = "me@example.com"; // wohin sollen Warn-Mails geschickt werden?
  17.  
  18. function main() {
  19.  
  20. var url = "https://tools.internet-marketing-inside.de/adwords-linkchecker.js";
  21. eval(UrlFetchApp.fetch(url).getContentText());
  22. DATAINSIDE.AdWordsApi.checkUrls({reportFoundPhrases:["page not found", "Staus: nicht lieferbar"], addParameterGclid:true, pause:200, removeParameter:["cl","bm","bmcl","cp","ag","sbm","ad","pl","bk","admt"], maxErrors:100, checkKeywords: true, checkAdsFinalUrls: true, checkSitelinks: true, checkDomains:true});
  23. if (false) {MailApp.sendEmail(g_sMailAddress, "!!!! Link Checker Dummy", "-");}
  24. }
  25.  
  26. // ENDE in Zwischenablage kopieren
  27. */
  28.  
  29. // Copyright data-inside GmbH (www.data-inside.de, holger.schulz@data-inside.de)
  30. // Diese AdWords Scripts lib kann von jedem kostenfrei genutzt werden. Die Nutzung erfolgt ohne Gewähr oder ohne Haftung. Die Veröffentlichung des Codes - auch in modifizierter Form - ist nicht gestattet.
  31. // This AdWords Scripts lib can be used by anyone at no charge. Use is granted without guarantee or liability. Redistribution of this code or derived code is prohibited.
  32.  
  33. // V1.0: 2014-08-19 first version
  34. // V1.1: 2014-11-18 / V1.1b: 2014-10-11: New:
  35. // - checks if domain of display URL is equal to destination URL
  36. // - checks if URL parameter gclid got lost in redirect chain
  37. // V1.2: 2014-11-19 - retry for status code 0 (Google bug?!)
  38. // V1.3: 2015-07-29 - final-url support
  39. // V1.4: 2015-08-16 - bugfix and kein_sale label just exists if bad URLs exists
  40. // V1.5: 2016-02-04 - bugfix: kein_sale was just added to the first ad with a bad URL
  41. // V1.6: 2016-02-26 - sitelink check support
  42. // V1.7: 2016-04-01 - Parameter checkAdsFinalUrls instead of checkAdsTargetUrl(s)
  43. // V1.8: 2016-08-22 - support for expanded text ads
  44. // V1.9: 2017-11-07 - Error message with account name and error line number
  45. //var g_sAccountUrl = "https://adwords.google.com/cm/CampaignMgmt?__u=123456789&__c=123456789"; // aus Browserzeile übernehmen
  46. //var g_sAccountName = "frei wählbarer Name des Kontos"; // Name im Kundencenter oder frei definierbar (erscheint im Mail-Betreff)
  47.  
  48. if (AdWordsApp.ads().withCondition("LabelNames CONTAINS_ANY ['Sale Anzeige fuer Skript', 'Sale-Anzeige für Skript']")){
  49.  
  50. DATAINSIDE = (typeof DATAINSIDE != 'undefined') ? DATAINSIDE : {};
  51. DATAINSIDE.Utils = DATAINSIDE.Utils || {};
  52. DATAINSIDE.Utils.endsWith = DATAINSIDE.Utils.endsWith || function(_sString, _sEndsWith) {
  53. return (_sString.indexOf(_sEndsWith, _sString.length - _sEndsWith.length) !== -1);
  54. };
  55. DATAINSIDE.Utils.startsWith = DATAINSIDE.Utils.startsWith || function(_sString, _sStartsWith) {
  56. return (_sString.indexOf(_sStartsWith) === 0);
  57. };
  58.  
  59. DATAINSIDE.Utils.setOrReplaceParameter = DATAINSIDE.Utils.setOrReplaceParameter || function(_sUrl, _sParameter, _sNewValueEncoded) {
  60. var re = new RegExp("([&\?])"+_sParameter+"=[^&]+(&?)", 'i');
  61. var sNewUrl = _sUrl;
  62. if (_sUrl.match(re)) {
  63. var n = _sUrl.indexOf("#");
  64. var sHash = (n === -1) ? "" : _sUrl.substring(n);
  65. if (null == _sNewValueEncoded) {
  66. sNewUrl = _sUrl.replace(re, "$1");
  67. if (DATAINSIDE.Utils.endsWith(sNewUrl, "&") === true) {
  68. sNewUrl = sNewUrl.substring(0, sNewUrl.length-1)+sHash;
  69. }
  70. if (DATAINSIDE.Utils.endsWith(sNewUrl, "?") === true) {
  71. sNewUrl = sNewUrl.substring(0, sNewUrl.length-1)+sHash;
  72. }
  73. } else {
  74. sNewUrl = _sUrl.replace(re, "$1"+_sParameter+"="+_sNewValueEncoded+"$2"+sHash);
  75. }
  76. } else if (null == _sNewValueEncoded) {
  77. return _sUrl;
  78. } else {
  79. var n = _sUrl.indexOf("?");
  80. if (n !== -1) {
  81. // ## http://example.com?aaa=bbb#xxxxx => http://example.com?newparam=newvalue&aaa=bbb#xxxxx
  82. sNewUrl = _sUrl.substring(0, n+1)+_sParameter+"="+_sNewValueEncoded+"&"+_sUrl.substring(n+1);
  83. } else {
  84. n = _sUrl.indexOf("#");
  85. if (n !== -1) {
  86. // ## http://example.com#xxxxx => http://example.com?newparam=newvalue#xxxxx
  87. sNewUrl = _sUrl.substring(0, n)+"?"+_sParameter+"="+_sNewValueEncoded+_sUrl.substring(n);
  88. } else {
  89. // ## http://example.com/abc.html => http://example.com/abc.html?newparam=newvalue
  90. sNewUrl = _sUrl+"?"+_sParameter+"="+_sNewValueEncoded;
  91. }
  92. }
  93. }
  94. return sNewUrl;
  95. };
  96.  
  97. DATAINSIDE.Utils.getHttpDomain = DATAINSIDE.Utils.getHttpDomain || function(_sUrl) {
  98. return _sUrl.match(/(https?:\/\/.[^/]+)/)[1];
  99. };
  100.  
  101.  
  102. DATAINSIDE.AdWordsUtils = DATAINSIDE.AdWordsUtils || {};
  103. DATAINSIDE.AdWordsUtils.logAllHeaders = DATAINSIDE.AdWordsUtils.logAllHeaders || function(_allHeaders) { // for debugging
  104. for (var prop in _allHeaders) {
  105. var myArray = [];
  106. if (Array.isArray(_allHeaders[prop]) ) {
  107. myArray=_allHeaders[prop];
  108. } else {
  109. myArray[0]=_allHeaders[prop];
  110. }
  111. myArray.forEach(function(el) {
  112. Logger.log(prop+ ": "+el);
  113. });
  114. }
  115. };
  116.  
  117. DATAINSIDE.AdWordsUtils.UrlResult = DATAINSIDE.AdWordsUtils.UrlResult || function(_sUrl, _bAddParameterGclid) {
  118. var that = this;
  119. var nMaxChainLength = 5;
  120. that.m_sUrl = _sUrl;
  121. that.m_bRedirect = false;
  122. that.m_httpResponseLast = null;
  123. that.m_nRedirects = 0; // 2 for example
  124. that.m_sRedirectChain = _sUrl; // http://schnelle-online.info/kalender --301--> http://www.schnelle-online.info/kalender --301--> http://www.schnelle-online.info/Kalender.html
  125. that.m_sRealDestinationUrl = null;
  126. that.m_error = null;
  127. that.m_bParameterValueReplaced= false;
  128. that.m_bFirstRequest = true;
  129. var regexpUrl = /{[^\&]+}/gi;
  130.  
  131. (function redirectResult(_sUrl, _bFollowRedirects) {
  132. try {
  133. var sUrl = _sUrl.replace(regexpUrl, "data-inside_LinkChecker");
  134. that.m_bParameterValueReplaced = (_sUrl != sUrl);
  135. if ((true === that.m_bFirstRequest) && (true === _bAddParameterGclid) && (sUrl.indexOf("gclid=") === -1)){
  136. if (sUrl.indexOf("?") == -1) {
  137. sUrl += "?";
  138. } else {
  139. sUrl += "&";
  140. }
  141. sUrl += "gclid=data-inside_LinkChecker";
  142. }
  143. that.m_bFirstRequest = false;
  144. that.m_sRealDestinationUrl = sUrl;
  145. var nResponseCode = -1;
  146. for (var i=0; i<3; i++) {
  147. that.m_httpResponseLast = UrlFetchApp.fetch(sUrl, {muteHttpExceptions: true, followRedirects: _bFollowRedirects} );
  148. nResponseCode = that.m_httpResponseLast.getResponseCode();
  149. if (nResponseCode != 0) {
  150. break;
  151. } else {
  152. Logger.log("nResponseCode = 0 for "+sUrl+" (followRedirects: "+_bFollowRedirects+")");
  153. Utilities.sleep(3000);
  154. }
  155. }
  156. if ((nResponseCode >= 1) && (nResponseCode > 1)) {
  157. //var sRedirectedUrl = that.m_httpResponseLast.getAllHeaders()['Location'];
  158. var sRedirectedUrl = that.m_httpResponseLast.getHeaders()['Location'];
  159. if (typeof sRedirectedUrl === 'undefined') {
  160. sRedirectedUrl = that.m_httpResponseLast.getHeaders()['location'];
  161. }
  162. //Logger.log("sRedirectedUrl 1: "+sRedirectedUrl);
  163. if ((null !== sRedirectedUrl) && (typeof sRedirectedUrl !== 'undefined')){
  164. if (DATAINSIDE.Utils.startsWith(sRedirectedUrl, "http") === false ) {
  165. if (DATAINSIDE.Utils.startsWith(sRedirectedUrl, "/") === true) {
  166. var sHttpDomain = DATAINSIDE.Utils.getHttpDomain(_sUrl);
  167. sRedirectedUrl = sHttpDomain+sRedirectedUrl;
  168. } else {
  169. that.m_sRedirectChain += " relative redirect to URL '"+sRedirectedUrl+"' not supported yet";
  170. that.m_error += " relative redirect to URL '"+sRedirectedUrl+"' not supported yet";
  171. }
  172. }
  173. // Logger.log("sRedirectedUrl 2: "+sRedirectedUrl);
  174. that.m_sRealDestinationUrl = sRedirectedUrl;
  175. if (_bFollowRedirects === false) {
  176. that.m_sRedirectChain += " --"+nResponseCode+"--> "+sRedirectedUrl;
  177. } else {
  178. that.m_sRedirectChain += " --...--> "+sRedirectedUrl;
  179. }
  180. ++that.m_nRedirects;
  181. that.m_bRedirect = true;
  182. if (that.m_nRedirects < nMaxChainLength-1) {
  183. redirectResult(sRedirectedUrl, false);
  184. } else if (that.m_nRedirects < nMaxChainLength) {
  185. that.m_sRedirectChain += " --???--> ??? (target URL unknown)";
  186. that.m_error += " quite many redirects";
  187. redirectResult(sRedirectedUrl, true);
  188. } else {
  189. that.m_sRedirectChain += " --...--> endless loop?";
  190. that.m_error = "endless redirect loop?";
  191. }
  192. } else {
  193. // fallback
  194. that.m_sRedirectChain += " --???--> ??? (target URL unknown)";
  195. redirectResult(sUrl, true); // try it again with automatic redirect :-(
  196. }
  197. } else if (nResponseCode >= 500) {
  198. that.m_sRedirectChain += " -> "+nResponseCode+" Error";
  199. that.m_error += " "+nResponseCode+" Error";
  200. }
  201. } catch (e) {
  202. that.m_error = e;
  203. that.m_sRedirectChain += " -> Error "+e;
  204. }
  205. })(_sUrl, false);
  206. if (true === that.m_bParameterValueReplaced) {
  207. that.m_sRedirectChain += ' (parameter values like "{keyword}" replaced by "data-inside_LinkChecker")';
  208. }
  209. /*
  210. if (true === _bAddParameterGclid) {
  211. that.m_sRedirectChain += ' (google analytics parameter gclid=data-inside_LinkChecker" added to URL)';
  212. }
  213. */
  214. this.toString = function() {
  215. return "m_sUrl: "+that.m_sUrl+"\r\nm_bRedirect: "+that.m_bRedirect+"\r\nm_nRedirects: "+that.m_nRedirects+"\r\nm_sRedirectChain: "+that.m_sRedirectChain+"\r\nm_error: "+that.m_error;
  216. };
  217. };
  218.  
  219. DATAINSIDE.Collection = DATAINSIDE.Collection || {};
  220. DATAINSIDE.Collection.Map = DATAINSIDE.Collection.Map || function() {
  221. var m_map = {};
  222.  
  223. this.put = function(_sKey, _sValue) {
  224. m_map[_sKey]=_sValue;
  225. };
  226.  
  227. this.get = function(_sKey) {
  228. return m_map[_sKey];
  229. };
  230.  
  231. this.remove = function(_sKey) {
  232. delete m_map[_value];
  233. };
  234.  
  235. this.contains = function(_sKey) {
  236. return (_sKey in m_map);
  237. };
  238.  
  239.  
  240. };
  241. DATAINSIDE.AdWordsApi = DATAINSIDE.AdWordsApi || {};
  242.  
  243. DATAINSIDE.AdWordsApi.logLabels = DATAINSIDE.AdWordsApi.logLabels || function() {
  244. Logger.log("Labels:");
  245. var labelIterator = AdWordsApp.labels().get();
  246. while (labelIterator.hasNext()) {
  247. var label = labelIterator.next();
  248. Logger.log("- "+label.getName());
  249. }
  250. };
  251.  
  252. (function() { // ## LinkChecker
  253. var s_timeStart = new Date().getTime();
  254. var s_nBadUrls = 0;
  255. var s_sBadUrls = [];
  256. var s_mapUrl2ok = null;
  257. // var nMaxStatusCode = 300; // not implemented yet
  258. var s_settingsLinkChecker;
  259. var s_bAddParameterGclid = false;
  260. var s_bCheckDomains = true; // display URL = destination URL?
  261. var s_sAccountName = null;
  262. var s_sAccountUrl = null;
  263.  
  264. DATAINSIDE.AdWordsApi.checkUrls = DATAINSIDE.AdWordsApi.checkUrls || function(_settingsLinkChecker) {
  265. try {
  266. if (g_sMailAddress == "me@example.com") {
  267. Logger.log("Please define your mail address instead of me@example.com and restart again.");
  268. return;
  269. }
  270. s_settingsLinkChecker = _settingsLinkChecker;
  271. s_sAccountName = ((typeof g_sAccountName === 'undefined') || (g_sAccountName === "") || (g_sAccountName == "AdWords Konto-Name") || (g_sAccountName == "AdWords account name")) ? AdWordsApp.currentAccount().getName() : g_sAccountName;
  272. s_sAccountUrl = ((typeof g_sAccountUrl === 'undefined') || (g_sAccountUrl === "") || (g_sAccountUrl == "https://adwords.google.com/cm/CampaignMgmt?__u=123456789&__c=123456789")) ? "https://adwords.google.com" : g_sAccountUrl;
  273. bCheckKeywords = ((typeof _settingsLinkChecker.checkKeywords === 'undefined') || (_settingsLinkChecker.checkKeywords === true)) ? true : false;
  274. bCheckAdsFinalUrl = (((typeof _settingsLinkChecker.checkAdsTargetUrl === 'undefined') && (typeof _settingsLinkChecker.checkAdsTargetUrls === 'undefined') && (typeof _settingsLinkChecker.checkAdsFinalUrls === 'undefined')) || (_settingsLinkChecker.checkAdsTargetUrl === true) || (_settingsLinkChecker.checkAdsTargetUrls === true) || (_settingsLinkChecker.checkAdsFinalUrls === true)) ? true : false;
  275. bCheckSitelinks = ((typeof _settingsLinkChecker.checkSitelinks === 'undefined') || (_settingsLinkChecker.checkSitelinks === true)) ? true : false;
  276. s_bCheckDomains = ((typeof _settingsLinkChecker.checkDomains === 'undefined') || (_settingsLinkChecker.checkDomains === true)) ? true : false;
  277. s_mapUrl2ok = new DATAINSIDE.Collection.Map();
  278. //if (s_settingsLinkChecker.reportRedirect !== true) {
  279. // nMaxStatusCode = 400;
  280. //}
  281. var sLabel = getAndManageLabels();
  282.  
  283. if (bCheckKeywords === true) {
  284. Logger.log("checkKeywords");
  285. checkUrlsImpl("keywords", sLabel);
  286. }
  287. if (bCheckAdsFinalUrl === true) {
  288. Logger.log("checkAdsFinalUrl");
  289. checkUrlsImpl("ads", sLabel);
  290. }
  291. if (bCheckSitelinks === true) {
  292. Logger.log("checkSitelinks");
  293. checkUrlsImpl("sitelinks", sLabel);
  294. }
  295. Logger.log("bad URLs: "+s_nBadUrls);
  296. if (s_nBadUrls > 0) {
  297. sendReportWithErrors();
  298. }
  299. } catch (e) {
  300. Logger.log(e+" (Line "+e.lineNumber+")");
  301. //if (e.message.indexOf("The label zz") === 0) {
  302. if ((e.message.indexOf("The label zz") === 0) || (e.message.indexOf("Failed to read from AdWords. Please wait a bit and try again.") === 0)) {
  303. Logger.log("AdWords Scripts bug (Google knows this bug and is about to fix it. Please wait for the bugfix.): Lable was not created. "+e);
  304. } else {
  305. MailApp.sendEmail(g_sMailAddress, "!!!! Exception in Script 'LinkChecker de Luxe' - "+AdWordsApp.currentAccount().getName(), "Account "+AdWordsApp.currentAccount().getName()+":\r\n "+e+"\r\nLine: "+e.lineNumber+"\r\n!!!!!! Please report this problem to holger.schulz@data-inside.de with script logs! Thanks");
  306. }
  307. throw e;
  308. }
  309. };
  310.  
  311. var sendReportWithErrors = function(_sPeriod) {
  312. var emailBody = [];
  313. emailBody.push("LinkChecker summary for account " + s_sAccountName + " " + AdWordsApp.currentAccount().getCustomerId() + " "+s_sAccountUrl+"\n");
  314.  
  315. for (var i=0; i < s_sBadUrls.length; i++) {
  316. var sUrl = s_sBadUrls[i];
  317. emailBody.push(sUrl+"\n");
  318. }
  319.  
  320. if (true === s_bAddParameterGclid) {
  321. emailBody.push("LinkChecker added parameter 'gclid=data-inside_LinkChecker' to all URLs to check for problems with this google analytics parameter which Google adds silently.\n");
  322. }
  323.  
  324.  
  325. MailApp.sendEmail(g_sMailAddress, "!!!! Link Checker "+ s_sAccountName, emailBody.join("\n"));
  326. };
  327.  
  328. var checkUrlsImpl = function (_sCheck, _sLabel) {
  329. var now = new Date().getTime();
  330. if (now - s_timeStart > 1500000) { // (25*60*1000 = 25 Minuten)
  331. // don'r report error any more ++s_nBadUrls;
  332. return true;
  333. }
  334.  
  335. var bLabelBadUrl = AdWordsApp.labels().withCondition("Name = 'kein_sale'").get().hasNext();
  336. var iterator = null;
  337. if (("keywords" == _sCheck) || ("ads" == _sCheck)) {
  338. var selector = ("keywords" == _sCheck) ? AdWordsApp.keywords() : AdWordsApp.ads();
  339. iterator = selector
  340. .withCondition("Status = ENABLED")
  341. .withCondition("AdGroupStatus = ENABLED")
  342. .withCondition("CampaignStatus = ENABLED")
  343. .withCondition("LabelNames CONTAINS_NONE ['"+_sLabel+"']")
  344. // .withCondition("DestinationUrl STARTS_WITH_IGNORE_CASE 'h'")
  345. // .orderBy("DestinationUrl")
  346. .orderBy("CampaignName")
  347. .orderBy("AdGroupName")
  348. .get();
  349. if (!iterator.hasNext()) {
  350. Logger.log("nothing to do");
  351. return false;
  352. }
  353. } else if ("sitelinks" == _sCheck) {
  354. var selector = AdWordsApp.extensions().sitelinks();
  355. iterator = selector.get();
  356. }
  357.  
  358. var sUrl = "";
  359. var sDisplayUrl = null;
  360. var sDisplayDomain = null;
  361. var nCheckContentLength = (typeof s_settingsLinkChecker.reportFoundPhrases === 'undefined') ? 0 : s_settingsLinkChecker.reportFoundPhrases.length;
  362. var nPause = (typeof s_settingsLinkChecker.pause === 'undefined') ? 0 : parseInt(s_settingsLinkChecker.pause, 10);
  363. var nMaxErrors = (typeof s_settingsLinkChecker.maxErrors === 'undefined') ? 100 : parseInt(s_settingsLinkChecker.maxErrors, 10);
  364. var regexpDomain = /^.*?([^\./]+\.[a-z]+)(?:[\/?#]|$)/i;
  365.  
  366. s_bAddParameterGclid = (typeof s_settingsLinkChecker.addParameterGclid === 'undefined') ? false : s_settingsLinkChecker.addParameterGclid;
  367. while (iterator.hasNext()) {
  368. if (s_nBadUrls >= nMaxErrors) {
  369. s_sBadUrls.push("Too many errors! Just first "+nMaxErrors+" will be reported");
  370. break;
  371. }
  372. if (now - s_timeStart > 1500000) { // (25*60*1000 = 25 Minuten)
  373. //++s_nBadUrls;
  374. //s_sBadUrls.push("Die Prüfung der URLs wurde abgebrochen, da die Ausführung das von Google vorgegebene Zeitfenster überschreitet. Wir arbeiten an einer Lösung!");
  375. break;
  376. }
  377. var entity = iterator.next();
  378. var result = checkUrl(entity, _sLabel, now, _sCheck, nCheckContentLength, nPause, nMaxErrors, regexpDomain, s_bAddParameterGclid);
  379. if (null === result) {
  380. continue;
  381. }
  382. }
  383. return true;
  384. };
  385.  
  386.  
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397. var checkUrl = function (entity, _sLabel, now, _sCheck, nCheckContentLength, nPause, nMaxErrors, regexpDomain, s_bAddParameterGclid) {
  398. var bLabelBadUrl = AdWordsApp.labels().withCondition("Name = 'kein_sale'").get().hasNext();
  399. var bSupportLable = (_sCheck != "sitelinks");
  400. var sUrl = "";
  401. var sDisplayUrl = null;
  402. var sDisplayDomain = null;
  403.  
  404. //sUrl = entity.getDestinationUrl();
  405. var sFinalUrl = getFinalUrl(entity);
  406. if (null === sFinalUrl) {
  407. // ## Keyword without URL
  408. return null;
  409. }
  410. var sMobileUrl = entity.urls().getMobileFinalUrl();
  411. var sUrls = [];
  412. sUrls.push(sFinalUrl);
  413. if (null !==sMobileUrl) {
  414. sUrls.push(sMobileUrl);
  415. }
  416. for (var i=0; i<sUrls.length; i++) {
  417. sUrl = sUrls[i]; // Destination, Final or MobileFinal
  418. var bRemoveParameter = (typeof s_settingsLinkChecker.removeParameter === 'undefined') ? false : ((s_settingsLinkChecker.removeParameter.length > 0) && (sUrl.indexOf("?") !== -1));
  419. if (true === bRemoveParameter) {
  420. //Logger.log("Vor remove : "+sUrl);
  421. for (var i=0; i<s_settingsLinkChecker.removeParameter.length; i++) {
  422. var sParameter = s_settingsLinkChecker.removeParameter[i];
  423. sUrl = DATAINSIDE.Utils.setOrReplaceParameter(sUrl, sParameter, null);
  424. }
  425. //Logger.log("Nach remove: "+sUrl);
  426. }
  427.  
  428. var sSetUrl = sUrl;
  429. if ((s_bCheckDomains === true) && (_sCheck == "ads")) {
  430. sDisplayUrl = entity.getDisplayUrl();
  431. if (null !== sDisplayUrl) { // null for expanded text ads
  432. sDisplayDomain = (regexpDomain.exec(sDisplayUrl)[1]).toLowerCase();
  433. sSetUrl = sDisplayDomain+sUrl; // check again if destination URL belongs to a different display URL domain.
  434. }
  435. }
  436. if (s_mapUrl2ok.get(sSetUrl) === false) {
  437. // ## Error for this sSetUrl already found => set kein_sale
  438. if (bSupportLable === true) {
  439. if (bLabelBadUrl === false) {bLabelBadUrl=true;createBadUrlLabel();}
  440. entity.applyLabel("kein_sale");
  441. }
  442. } else if (s_mapUrl2ok.contains(sSetUrl) === false) {
  443. s_mapUrl2ok.put(sSetUrl, true);
  444. urlResult = new DATAINSIDE.AdWordsUtils.UrlResult(sUrl, s_bAddParameterGclid);
  445. //Logger.log("URL: "+urlResult.m_sRedirectChain);
  446. var nResponseCode = (urlResult.m_httpResponseLast !== null) ? urlResult.m_httpResponseLast.getResponseCode() : 999;
  447. var then = new Date().getTime();
  448. if ((0 !== nPause) && ((nPause - (then - now)) > 0)) {
  449. Utilities.sleep(nPause - (then - now));
  450. }
  451. now = new Date().getTime();
  452.  
  453. if (nResponseCode == 200) {
  454. //var bFoundPhrase = false;
  455. var bBadUrl = false;
  456. if ((s_bCheckDomains === true) && (_sCheck == "ads")) {
  457. var sDestinationDomain = (regexpDomain.exec(urlResult.m_sRealDestinationUrl)[1]).toLowerCase();
  458. if ((null !== sDisplayDomain) && (sDisplayDomain != sDestinationDomain)) {
  459. ++s_nBadUrls;
  460. bBadUrl = true;
  461. s_mapUrl2ok.put(sSetUrl, false);
  462. if (bSupportLable === true) {
  463. if (bLabelBadUrl === false) {bLabelBadUrl=true;createBadUrlLabel();}
  464. entity.applyLabel("kein_sale");
  465. }
  466. s_sBadUrls.push("Display domain name '"+sDisplayUrl+"' is different than in (redirected) destination URL "+urlResult.m_sRedirectChain);
  467. Logger.log(" Display domain name '"+sDisplayUrl+"' is different than in (redirected) destination URL "+urlResult.m_sRedirectChain);
  468. }
  469. }
  470. if (s_bAddParameterGclid === true) {
  471. if (urlResult.m_sRealDestinationUrl.indexOf("gclid=data-inside_LinkChecker") === -1) {
  472. if (bBadUrl === false) {
  473. bBadUrl = true;
  474. ++s_nBadUrls;
  475. //if (bLabelBadUrl === false) {bLabelBadUrl=true;createBadUrlLabel();}
  476. //entity.applyLabel("kein_sale");
  477. }
  478. s_mapUrl2ok.put(sSetUrl, false);
  479. if (bSupportLable === true) {
  480. if (bLabelBadUrl === false) {bLabelBadUrl=true;createBadUrlLabel();}
  481. entity.applyLabel("kein_sale");
  482. }
  483. var sInfo = (_sCheck == "sitelinks") ? " (sitelink '"+entity.getLinkText()+"')" : "";
  484. s_sBadUrls.push("Google Analytics tracking parameter 'gclid' got lost in redirection chain"+sInfo+": "+urlResult.m_sRedirectChain);
  485. Logger.log("Google Analytics tracking parameter 'gclid' got lost in redirection chain"+sInfo+": "+urlResult.m_sRedirectChain);
  486. }
  487. }
  488. if (nCheckContentLength !== 0) {
  489. //if ((nResponseCode >= 300) && (
  490. var sText = urlResult.m_httpResponseLast.getContentText();
  491. for (var i=0; i < nCheckContentLength; i++){
  492. var sPhrase = s_settingsLinkChecker.reportFoundPhrases[i];
  493. if (sText.indexOf(sPhrase) !== -1) {
  494. if (bBadUrl === false) {
  495. bBadUrl = true;
  496. ++s_nBadUrls;
  497. }
  498. s_mapUrl2ok.put(sSetUrl, false);
  499. if (bSupportLable === true) {
  500. if (bLabelBadUrl === false) {bLabelBadUrl=true;createBadUrlLabel();}
  501. entity.applyLabel("kein_sale");
  502. }
  503. var sInfo = (_sCheck == "sitelinks") ? " (sitelink '"+entity.getLinkText()+"')" : "";
  504. s_sBadUrls.push("'"+sPhrase+"' found in "+urlResult.m_sRedirectChain+sInfo);
  505. Logger.log(" Phrase error: '"+sPhrase+"' found in "+urlResult.m_sRedirectChain+sInfo);
  506. //bFoundPhrase = true;
  507. break;
  508. }
  509. }
  510. }
  511. } else {
  512. ++s_nBadUrls;
  513. s_mapUrl2ok.put(sSetUrl, false);
  514. if (bSupportLable === true) {
  515. if (bLabelBadUrl === false) {bLabelBadUrl=true;createBadUrlLabel();}
  516. entity.applyLabel("kein_sale");
  517. }
  518. var sInfo = (_sCheck == "sitelinks") ? " (sitelink '"+entity.getLinkText()+"')" : "";
  519. if (nResponseCode === 999) { // urlResult.m_error !== null) {
  520. s_sBadUrls.push(nResponseCode+": "+urlResult.m_sRedirectChain+" (error "+urlResult.m_error+")"+sInfo);
  521. } else {
  522. s_sBadUrls.push(nResponseCode+": "+urlResult.m_sRedirectChain+sInfo);
  523. }
  524. }
  525. }
  526. }
  527. if (bSupportLable === true) {entity.applyLabel(_sLabel);} // mark as checked today (explicit this or another keyword/ad with the 'same' URL
  528. };
  529.  
  530. var getAndManageLabels = function() {
  531. var sTimeZone = AdWordsApp.currentAccount().getTimeZone();
  532. var time = new Date();
  533. var sDate = Utilities.formatDate(time, sTimeZone, "yyyyMMdd");
  534. var sLabelToday = "zzURLchecked"+sDate;
  535.  
  536. // ## 1. check for first run today
  537. var labelIterator = AdWordsApp.labels().withCondition("Name = '"+sLabelToday+"'").get();
  538. var bFirstRunToday = !labelIterator.hasNext();
  539. var labelIteratorBadUrl = AdWordsApp.labels().withCondition("Name = 'kein_sale'").get();
  540.  
  541. // ## delete old labels
  542. if (true == bFirstRunToday) {
  543. var labelIterator = AdWordsApp.labels().withCondition("Name STARTS_WITH 'zzURLchecked'").get();
  544. while (labelIterator.hasNext()) {
  545. var label = labelIterator.next();
  546. // ## found an old label
  547. //Logger.log("remove old label "+label.getName());
  548. label.remove();
  549. }
  550. AdWordsApp.createLabel(sLabelToday, "data-inside LinkChecker", "white");
  551. if (labelIteratorBadUrl.hasNext()) {
  552. var label = labelIteratorBadUrl.next();
  553. label.remove(); // re
  554. }
  555. //AdWordsApp.createLabel("kein_sale", "data-inside LinkChecker", "white");
  556. } else {
  557. //if (labelIteratorBadUrl.hasNext() == false) {
  558. // //Logger.log("createLabel kein_sale");
  559. // AdWordsApp.createLabel("kein_sale", "data-inside LinkChecker", "white");
  560. //}
  561. }
  562. //DATAINSIDE.AdWordsApi.logLabels();
  563. return sLabelToday;
  564. };
  565.  
  566. var createBadUrlLabel = function() {
  567. AdWordsApp.createLabel("kein_sale", "data-inside LinkChecker", "white");
  568. };
  569.  
  570. function getFinalUrl(el) {
  571. var urls = el.urls();
  572. var sFinalUrl = urls.getFinalUrl();
  573. if ((null === sFinalUrl) && (typeof(el.getDestinationUrl) === "function")) {
  574. sFinalUrl = el.getDestinationUrl();
  575. }
  576. if ((null != sFinalUrl) && ((sFinalUrl.indexOf("{unescapedlpurl}")!=-1) || (sFinalUrl.indexOf("{escapedlpurl}")!=-1) || (sFinalUrl.indexOf("{lpurl")!=-1))) {
  577. sFinalUrl = null; // unable to check these urls
  578. }
  579. return sFinalUrl;
  580. }
  581. })(); // ## LinkChecker
  582.  
  583. }
  584.  
  585. else {
  586. Logger.log("Anzeige ohne Sale AZG uebersprungen");
  587. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement