SPAG, czyli Single Product Ad Groups, to koncept, który zakłada tworzenie jednego produktu dla jednej grupy reklam.
Rozwiązanie to pozwala analizować wyszukiwane hasła na poziomie produktu (w klasycznej strukturze opcja ta nie jest dostępna).
W niektórych branżach podział tego typu może pozytywnie wpłynąć na efektywność reklam.
Niestety ręczne przeprowadzenie takiego procesu jest niezwykle czasochłonne.
Szczególnie jeśli nasz sklep posiada szeroki asortyment produktów.
Na szczęście Google Ads umożliwia automatyzację tego procesu za pomocą skryptu.
Przygotowane rozwiązanie tworzy SPAG-i w wybranej kampanii – jej nazwę należy wprowadzić do zmiennej „CAMPAIGN_NAME” (kampania musi być wcześniej utworzona ręcznie).
Do kampanii tej zostaną dodane tylko te produkty, które wybraliśmy za pomocą etykiety w pliku produktów.
Więcej na temat etykiet w oficialnej dokumentacji:
https://support.google.com/google-ads/answer/6275295
Przykładowa konfiguracja:
1. Tworzymy ręcznie pustą kampanię np. SPAG – wszystkie produkty
2. Wprowadzamy nazwę kampanii do zmiennej CAMPAIGN_NAME = „SPAG – wszystkie produkty”
3. Wprowadzamy ID naszego Merchant Center do zmiennej MERCHANT_ID
4. W pliku produktów za pomocą własnej etykiety oznaczamy produkty, które chcemy, aby zostały uwzględnione w procesie tworzenia SPAG-ów, np. własna etykieta 1 i wartość: „WYDZIEL”.
Dalej w zmiennej „CUSTOM_LABEL_NUMBER” nadajemy wartość: „customLabel1”, a w zmiennej „CUSTOM_LABEL_VALUE” wartość „WYDZIEL”, czyli tę nadaną w pliku produktów.
5. W zaawansowanych ustawieniach włączamy „Shopping content”:
https://developers.google.com/google-ads/scripts/docs/features/advanced-apis
Harmonogram: co godzinę
Po więcej na temat Skryptów zapraszam na grupę FB:
https://www.facebook.com/groups/zaawansowane.google.ads
//Updated on 05.04.2020: Code structure improvements /* Copyright 2019 Krzysztof Bycina, www.LiveAds.pl Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ // -------------------------------------------- Configuration: var MERCHANT_ID = 'ENTER THE MERCHANT ID HERE'; var CAMPAIGN_NAME = 'ENTER THE DESTINATION CAMPAIGN NAME HERE'; // Destination shopping campaign var CUSTOM_LABEL_NUMBER = "customLabel4"; // Possible values: customLabel0, customLabel1, customLabel2, customLabel3, customLabel4 var CUSTOM_LABEL_VALUE = "ENTER YOUR VALUE HERE"; // Only products with this value will be build. var STARTING_BID = 0.5; // What bid for created products? // -------------------------------------------- End of the configuration function main() { verifyCampaign(); verifyMerchantId(); verifyCustomLabel(); var currentAdGroups = verifyCurrentAdGroups(); var merchantData = fetchTheData(currentAdGroups); if (merchantData.titleData.length > 0) { Logger.log("Creating Ad groups..."); createShoppingAdGroups(merchantData); } else { Logger.log("There are no products to build."); } } function createShoppingAdGroups(merchantData) { var shoppingCampaign = AdWordsApp.shoppingCampaigns() .withCondition("CampaignName = '" + CAMPAIGN_NAME + "'") .get() .next(); for (i = 0; i < merchantData.titleData.length; i++) { Logger.log(merchantData.titleData[i] + " // " + merchantData.itemIdData[i]) //build an ad group var adGroupOperation = shoppingCampaign.newAdGroupBuilder() .withName(merchantData.titleData[i] + " // " + merchantData.itemIdData[i]) .withStatus("ENABLED") .build(); //build a product var shoppingAdGroup = adGroupOperation.getResult(); shoppingAdGroup.createRootProductGroup(); shoppingAdGroup.rootProductGroup().newChild() .itemIdBuilder() .withBid(STARTING_BID) .withValue(merchantData.itemIdData[i]) .build(); //build an ad var ad = shoppingAdGroup .newAdBuilder() .build() .getResult(); //Exclude everything else: findOtherCase = shoppingAdGroup.productGroups().get(); while (findOtherCase.hasNext()) { var isThisOtherCase = findOtherCase.next() if (isThisOtherCase.isOtherCase()) { isThisOtherCase.exclude() } } } } function fetchTheData(currentAdGroups) { var theData = { titleData: [], itemIdData: [] } var productNumber = 0 var pageToken; var pageNum = 1; var maxResults = 250; do { var products = ShoppingContent.Products.list(MERCHANT_ID, { pageToken: pageToken, maxResults: maxResults }); if (products.resources) { for (var i = 0; i < products.resources.length; i++) { if (products.resources[i][CUSTOM_LABEL_NUMBER] === CUSTOM_LABEL_VALUE && products.resources[i][CUSTOM_LABEL_NUMBER]) { var newAdGroupName = products.resources[i].title + " // " + products.resources[i].offerId; //Check if the current ad group already exists if (currentAdGroups.indexOf(newAdGroupName) === -1.0) { theData.titleData.push(products.resources[i].title); theData.itemIdData.push(products.resources[i].offerId); } } } } pageToken = products.nextPageToken; pageNum++; } while (pageToken); Logger.log("Total products to build: " + theData.titleData.length); return theData; } function verifyCustomLabel() { if (CUSTOM_LABEL_NUMBER === "customLabel0" || CUSTOM_LABEL_NUMBER === "customLabel1" || CUSTOM_LABEL_NUMBER === "customLabel2" || CUSTOM_LABEL_NUMBER === "customLabel3" || CUSTOM_LABEL_NUMBER === "customLabel4") {} else { throw new Error("There is a problem with the CUSTOM_LABEL_NUMBER configuration. Remember: it is CASE SENSITIVE."); } } function verifyMerchantId() { if (isNaN(MERCHANT_ID)) { throw new Error("Error: Please, enter a correct Merchand ID number."); } } function verifyCurrentAdGroups() { var adGroupsData = []; var adGroupIterator = AdsApp .shoppingAdGroups() .withCondition("CampaignName = '" + CAMPAIGN_NAME + "'") .get(); while (adGroupIterator.hasNext()) { var adGroup = adGroupIterator.next(); adGroupsData.push(adGroup.getName()); } Logger.log("Total products in the Campaign: " + adGroupsData.length); return adGroupsData; } function verifyCampaign() { var campaign = AdWordsApp.shoppingCampaigns().withCondition("Name = '" + CAMPAIGN_NAME + "'").get(); if (campaign.totalNumEntities() === 0) { throw new Error("Shopping Campaign with the name: " + CAMPAIGN_NAME + " Dosen't exist. Verify the script configuration & run it again."); } }
Hejka,
Świetny pomysł z tym skryptem, jednak mimo wszystko wciąż nie udało mi się go odpalić.
czy możesz napisać jak powinienem poprawić skrypt aby zamiast CUSTOM_LABEL_NUMBER, wykorzystać kolumnę z „marką produktu” a jako wydziel podać „brand”?
Drugi pomysł który był by równie wartosciowy to nie korzystać z w ogólę z „CUSTOM_LABEL_NUMBER”, tylko utworzyć jedną kampanie która ma wszystkie produkty.
Cześć Piotr,
dzięki za komentarz. Napisz do mnie na [email protected].
Postaram się pomóc.
Chciałbym dopytać jak wygląda sytuacja gdy np dziś dodam SPAG z feeda który ma np 300 produktów. Za 2 tygodnie 10% produktów wypada i dochodzi 20% nowych produktów.
Czy nie masz jakiegoś pomysłu na aktualizację takiej kampanii SPAG (pauzowanie produktów ze statusem brak w magazynie to się powinno dać zrobić regułą) oraz dodawanie nowych aktualnych których nie ma obecnie?
Pozdrawiam Tomasz.
Cześć Tomasz,
skrypt radzie sobie z powyższym scenariuszem. Należy ustawić częstotliwość na: raz dziennie, w godzinach nocnych.
Gdy pojawią się nowe produkty w Merchant Center, to skrypt doda je automatycznie (sprawdza co jest obecnie i co należy jeszcze dodać). Produkty, które nie są aktywne w Merchant, nie powodują wyświetleń reklamy, więc nie trzeba ich wstrzymywać.
Hmm. A co z sytuacją gdy zmieniają się tytuły produktów (optymalizacja)? Hmm. Czy jest jakaś opcja żeby spagi tworzyły się z tytułem ad group jako id produktu? 🙂
Wszystko da się zrobić 🙂
Cześć Krzysztof,
jakiś czas temu znalazłem Twój skrypt, dziś chciałem go uruchomić. Wypełniłem wszystkie potrzebne dane, jednak za każdym razem skrypt wyrzuca błąd: https://monosnap.com/direct/TS8pHQMUG7GWiME4JGthpifFwhLXPs
Produkty w GMC są zatwierdzone, gotowe do wyświetlenia, a jednak skrypt wskazuje 0 produktów. Mogę liczyć na Twoją pomoc?
Pozdrawiam
Cześć Adrian,
Zapraszam na moją grupę FB. Tam pomagam w takich sprawach.