<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>adtraffic</title>
	<atom:link href="https://www.adtraffic.de/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.adtraffic.de/</link>
	<description>a media plan company</description>
	<lastBuildDate>Tue, 30 Sep 2025 11:16:15 +0000</lastBuildDate>
	<language>de</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9</generator>

<image>
	<url>https://www.adtraffic.de/wp-content/uploads/2023/08/adtraffic-favicon-150x150.png</url>
	<title>adtraffic</title>
	<link>https://www.adtraffic.de/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Der einfache Einstieg mit Google Ads Scripts</title>
		<link>https://www.adtraffic.de/der-einfache-einstieg-mit-google-ads-scripts/</link>
		
		<dc:creator><![CDATA[rs]]></dc:creator>
		<pubDate>Tue, 30 Sep 2025 11:16:14 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<guid isPermaLink="false">https://www.adtraffic.de/?p=1912</guid>

					<description><![CDATA[<p>Automatisierungen begegnen uns in vielen alltäglichen Situationen. Sie sparen uns viel Zeit und Nerven und eröffnen uns zusätzliche Möglichkeiten. Sei es der Kaffeevollautomat, der Geschirrspüler oder das Navi. Mit Google Ads Scripts lassen sich alltägliche Arbeiten im Google Ads Konto automatisieren, was uns neben der Zeitersparnis auch zusätzliche Sicherheit verschafft. Durch gezielten Einsatz von Google [&#8230;]</p>
<p>The post <a href="https://www.adtraffic.de/der-einfache-einstieg-mit-google-ads-scripts/">Der einfache Einstieg mit Google Ads Scripts</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Automatisierungen begegnen uns in vielen alltäglichen Situationen. Sie sparen uns viel Zeit und Nerven und eröffnen uns zusätzliche Möglichkeiten. Sei es der Kaffeevollautomat, der Geschirrspüler oder das Navi. Mit Google Ads Scripts lassen sich alltägliche Arbeiten im Google Ads Konto automatisieren, was uns neben der Zeitersparnis auch zusätzliche Sicherheit verschafft. Durch gezielten Einsatz von Google Ads Scripts wird die Performance im Google Ads Konto erheblich verbessert.</p>



<p>Am 26.09.2025 hat unser Geschäftsführer Richard Stinauer auf dem OMT dazu einen Vortrag gehalten. Die gezeigte Präsentation könnt Ihr Euch hier herunterladen:</p>



<p><a href="https://www.adtraffic.de/wp-content/uploads/adtraffic-Richard-Stinauer-OMT-2025-Der-einfache-Einstieg-mit-Google-Ads-Scripts-Handout.pdf"><strong>adtraffic &#8211; Richard Stinauer &#8211; OMT 2025 &#8211; Der einfache Einstieg mit Google Ads Scripts &#8211; Handout</strong></a></p>



<p>Der Impulsvortrag richtete sich vor allem an Neulinge und Anfänger; Personen, die also noch gar nicht mit Google Ads Scripts gearbeitet haben oder bisher nur erste Gehversuche gewagt haben. Im Vortrag ging Richard Stinauer deshalb zunächst auf drei einfache Einstiegsmöglichkeiten ein:</p>



<ul class="wp-block-list">
<li>Integrierte Lösungen in Google Ads</li>



<li>Google Ads Skriptvorlagen</li>



<li>Fertige Skripte von Drittanbietern</li>
</ul>



<p>Manche Anforderungen lassen sich mit fertigen Vorlagen nicht abbilden. In zweiten Teil der Präsentation mit dem Titel &#8220;Dein erstes eigenes Skript&#8221; zeigte Richard Stinauer auf, wie man auch ohne Kenntnisse in der Softwareentwicklung in das Thema Google Ads Scripts einsteigen kann. Neben Voraussetzungen und Referenzen erklärte er auch anhand eines sehr einfachen Code-Beispiels die grundsätzliche Logik eines Google Ads Scripts.</p>



<p>Im abschließenden dritten Teil seines Vortrags erläuterte Richard, wie KI beim Einstieg, sowie bei der Erstellung und beim Debuggen von Google Ads Skripten helfen kann. Dabei war ihm wichtig, zu erwähnen, dass KI zwar ein echter Produktivitäts-Booster sein und die Lernphase deutlich beschleunigen kann, andererseits aber auch gelegentlich falsche Antworten liefert und deshalb nicht das Verständnis ersetzt. Sein Fazit: KI gerne als Co-Pilot einsetzen, aber bitte nicht als Autopilot.</p>
<p>The post <a href="https://www.adtraffic.de/der-einfache-einstieg-mit-google-ads-scripts/">Der einfache Einstieg mit Google Ads Scripts</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Video Tracking ohne JS API und ohne Google Tag Manager</title>
		<link>https://www.adtraffic.de/video-tracking-ohne-js-api-und-ohne-google-tag-manager/</link>
		
		<dc:creator><![CDATA[rs]]></dc:creator>
		<pubDate>Sun, 11 May 2025 08:33:40 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<guid isPermaLink="false">https://www.adtraffic.de/?p=1894</guid>

					<description><![CDATA[<p>Die Alternative zu den “Ereignissen für optimierte Analysen” in GA4 GA4 ermöglicht die automatische Messung von Interaktionen mit auf der Webseite eingebundenen Videos, sofern ein Player mit JS API-Unterstützung verwendet wird. Bei der Verwendung anderer Video Player benötigt man einen Workaround mit EventListeners. Für den Google Tag Manager hat Julius Fedorovicius eine Anleitung auf AnalyticsMania [&#8230;]</p>
<p>The post <a href="https://www.adtraffic.de/video-tracking-ohne-js-api-und-ohne-google-tag-manager/">Video Tracking ohne JS API und ohne Google Tag Manager</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Die Alternative zu den “Ereignissen für optimierte Analysen” in GA4</h2>



<p>GA4 ermöglicht die automatische Messung von Interaktionen mit auf der Webseite eingebundenen Videos, sofern ein Player mit <a href="https://developers.google.com/youtube/player_parameters#enablejsapi">JS API-Unterstützung</a> verwendet wird. Bei der Verwendung anderer Video Player benötigt man einen Workaround mit <a href="https://www.w3schools.com/js/js_htmldom_eventlistener.asp">EventListeners</a>. Für den Google Tag Manager hat Julius Fedorovicius eine <a href="https://www.analyticsmania.com/post/track-html5-video-player-with-google-analytics-4-and-google-tag-manager/">Anleitung auf AnalyticsMania</a> veröffentlicht. Der nachfolgende Implementierungsvorschlag dient für Google Tags, die ohne Tag Manager eingebunden wurden.</p>



<h2 class="wp-block-heading">Voraussetzung und Empfehlung</h2>



<p>Auf der Webseite ist der Google Tag bereits implementiert. Eine Anleitung dazu findet sich in der <a href="https://support.google.com/analytics/answer/15756615?hl=de">Google Analytics-Hilfe</a>. Wir empfehlen zudem die Verwendung eines Consent Management Tools.</p>



<h2 class="wp-block-heading">Video auswählen und Variablen vorbereiten</h2>



<p>Das Video-Element auf der jeweiligen Seite wird mit einem Selektor ausgewählt. Zur späteren Verwendung können z.B. die URL und der Titel des Videos in Variablen gespeichert werden.</p>



<p><strong>const</strong> video = document.querySelector(&#8220;video&#8221;);<br><br><strong>var</strong> videoUrl = video.currentSrc;<br><strong>var</strong> videoTitle = video.title;</p>



<p>Zur Begrenzung des Trackings auf jeweils ein Event je Seitenaufruf werden zusätzliche Statusvariablen definiert. Bei erfolgtem Tracking wird die zugehörige Variable später auf “true” gesetzt.</p>



<p><strong>var</strong> started = false;<br><strong>var</strong> played10 = false;<br><strong>var</strong> played25 = false;<br><strong>var</strong> played50 = false;<br><strong>var</strong> played75 = false;<br><strong>var</strong> played90 = false;<br><strong>var</strong> ended = false;</p>



<p>Innerhalb der Event Handler wird der Status dieser Statusvariablen abgefragt. Sofern das Event noch nicht getrackt wurde, wird ein Tracking-Aufruf an den Google Tag gesendet.</p>



<h2 class="wp-block-heading">Der “Video Start” Event Handler und Standard Parameter</h2>



<p>Für den Start eines Videos mit Übergabe des Titels und der URL sieht der Event Handler wie folgt aus:</p>



<p>video.addEventListener(&#8220;play&#8221;, (event) =&gt; {<br>&nbsp; &nbsp; <strong>if</strong> (started === false) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_start&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 0<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; started = true;<br>&nbsp; &nbsp; }<br>});</p>



<p>Dabei können die zuvor definierten Variablen als zusätzliche Parameter angehängt werden. In GA4 werden folgende Bezeichnungen für die vordefinierten Dimensionen und Metriken verwendet:&nbsp;</p>



<ul class="wp-block-list">
<li>video_current_time</li>



<li>video_duration</li>



<li>video_percent</li>



<li>video_provider</li>



<li>video_title</li>



<li>video_url</li>



<li>visible (boolesch)</li>
</ul>



<h2 class="wp-block-heading">Der “Video Progress” Event Handler</h2>



<p>Das Event für den Fortschritt der Videowiedergabe wird vom Browser regelmäßig während der Wiedergabe gefeuert. Durch Abfrage der aktuellen Wiedergabezeit kann auf Basis der Gesamtlänge des Videos die prozentuale Wiedergabedauer berechnet werden. Das Tracking der gewünschten Einzelschritte kann in einem Event Handler zusammengefasst werden. In diesem Beispiel werden Tracking Events jeweils bei 10, 25, 50, 75 und 90 erreichten Prozent der Gesamtdauer an den Google Tag gesendet. Die Aktualisierung der korrespondierenden Statusvariablen verhindert ein mehrfaches Tracking der Fortschritte.</p>



<p>video.addEventListener(&#8220;progress&#8221;, (event) =&gt; {<br>&nbsp; &nbsp; <strong>if</strong> (played10 === false &amp; video.currentTime / video.duration &gt;= 0.1) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_progress&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 10<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; played10 = true;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; <strong>if</strong> (played25 === false &amp; video.currentTime / video.duration &gt;= 0.25) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_progress&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 25<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; played25 = true;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; <strong>if</strong> (played50 === false &amp; video.currentTime / video.duration &gt;= 0.5) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_progress&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 50<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; played50 = true;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; <strong>if</strong> (played75 === false &amp; video.currentTime / video.duration &gt;= 0.75) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_progress&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 75<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; played75 = true;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; <strong>if</strong> (played90 === false &amp; video.currentTime / video.duration &gt;= 0.9) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_progress&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 90<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; played90 = true;<br>&nbsp; &nbsp; }<br>});</p>



<h2 class="wp-block-heading">Der kombinierte Video Tracking Code</h2>



<figure class="wp-block-table"><table class="has-fixed-layout"><tbody><tr><td><strong>const</strong> video = document.querySelector(&#8220;video&#8221;);<br><br><strong>var</strong> videoUrl = video.currentSrc;<br><strong>var</strong> videoTitle = video.title;<br><strong>var</strong> started = false;<br><strong>var</strong> played10 = false;<br><strong>var</strong> played25 = false;<br><strong>var</strong> played50 = false;<br><strong>var</strong> played75 = false;<br><strong>var</strong> played90 = false;<br><strong>var</strong> ended = false;<br><br>video.addEventListener(&#8220;play&#8221;, (event) =&gt; {<br>&nbsp; &nbsp; <strong>if</strong> (started === false) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_start&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 0<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; started = true;<br>&nbsp; &nbsp; }<br>});<br><br>video.addEventListener(&#8220;progress&#8221;, (event) =&gt; {<br>&nbsp; &nbsp; <strong>if</strong> (played10 === false &amp; video.currentTime / video.duration &gt;= 0.1) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_progress&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 10<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; played10 = true;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; <strong>if</strong> (played25 === false &amp; video.currentTime / video.duration &gt;= 0.25) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_progress&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 25<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; played25 = true;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; <strong>if</strong> (played50 === false &amp; video.currentTime / video.duration &gt;= 0.5) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_progress&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 50<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; played50 = true;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; <strong>if</strong> (played75 === false &amp; video.currentTime / video.duration &gt;= 0.75) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_progress&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 75<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; played75 = true;<br>&nbsp; &nbsp; }<br>&nbsp; &nbsp; <strong>if</strong> (played90 === false &amp; video.currentTime / video.duration &gt;= 0.9) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_progress&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 90<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; played90 = true;<br>&nbsp; &nbsp; }<br>});<br><br>video.addEventListener(&#8220;ended&#8221;, (event) =&gt; {<br>&nbsp; &nbsp; <strong>if</strong> (ended === false) {<br>&nbsp; &nbsp; &nbsp; &nbsp; gtag(&#8216;event&#8217;, &#8216;video_complete&#8217;, {<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_url&#8217;: videoUrl,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_title&#8217;: videoTitle,<br>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &#8216;video_percent&#8217;: 100<br>&nbsp; &nbsp; &nbsp; &nbsp; });<br>&nbsp; &nbsp; &nbsp; &nbsp; ended = true;<br>&nbsp; &nbsp; }<br>});</td></tr></tbody></table></figure>



<p>Dieser Code sollte analog zum Google Tag nur nach Zustimmung des Nutzers ausgeführt werden, um unnötige und fehlerhafte Aufrufe zu vermeiden.</p>
<p>The post <a href="https://www.adtraffic.de/video-tracking-ohne-js-api-und-ohne-google-tag-manager/">Video Tracking ohne JS API und ohne Google Tag Manager</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Instagram Summit 2024: Trends und Highlights im Überblick</title>
		<link>https://www.adtraffic.de/instagram-summit-2024-trends-und-highlights-im-ueberblick/</link>
		
		<dc:creator><![CDATA[rs]]></dc:creator>
		<pubDate>Fri, 04 Oct 2024 15:14:21 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<guid isPermaLink="false">https://www.adtraffic.de/?p=1393</guid>

					<description><![CDATA[<p>Der Instagram Summit 2024 bot eine Fülle an spannenden Einblicken und hilfreichen Strategien für alle, die auf Instagram erfolgreicher werden wollen. Experten aus verschiedenen Bereichen teilten ihre neuesten Tipps und zeigten, wie man Reichweite, Engagement und Community-Aufbau gezielt steigern kann. Wichtige Trends &#38; Erkenntnisse 1. Automatisierung macht den Unterschied Ein großes Thema war die Automatisierung [&#8230;]</p>
<p>The post <a href="https://www.adtraffic.de/instagram-summit-2024-trends-und-highlights-im-ueberblick/">Instagram Summit 2024: Trends und Highlights im Überblick</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Der <strong>Instagram Summit 2024</strong> bot eine Fülle an spannenden Einblicken und hilfreichen Strategien für alle, die auf Instagram erfolgreicher werden wollen. Experten aus verschiedenen Bereichen teilten ihre neuesten Tipps und zeigten, wie man Reichweite, Engagement und Community-Aufbau gezielt steigern kann.</p>



<h4 class="wp-block-heading"><strong>Wichtige Trends &amp; Erkenntnisse</strong></h4>



<p><strong>1. Automatisierung macht den Unterschied</strong></p>



<p>Ein großes Thema war die Automatisierung von Nachrichten und Interaktionen auf Instagram. Tools wie ManyChat helfen dabei, DMs zu automatisieren, um schneller auf Anfragen zu reagieren und Leads effizienter zu generieren. Natasha Willis und Amberlea Henriques demonstrierten, wie diese Tools eingesetzt werden können, um gleichzeitig persönlich und skalierbar zu kommunizieren – sei es durch einfache Chat-Flows oder komplexere Verkaufsfunnels.</p>



<p><strong>2. Künstliche Intelligenz unterstützt bei der Content-Erstellung</strong></p>



<p>KI spielt mittlerweile eine zentrale Rolle in der Inhaltserstellung. Caroline Flett und Phil Pallen zeigten, wie man mit Tools wie ChatGPT und Adobe Express den Prozess der Content-Produktion vereinfacht. Von der Textgenerierung bis zur Videoaufbereitung gibt es viele Möglichkeiten, durch KI zeitsparend Inhalte auf hohem Niveau zu erstellen.</p>



<p><strong>3. Storytelling und Authentizität stehen im Vordergrund</strong></p>



<p>Eine der wichtigsten Botschaften: Hebe dich durch echte Geschichten von der Masse ab. Valeria Lipovetsky und Tori Dunlap betonten, wie wichtig es ist, authentische Inhalte zu teilen und die Community aufzubauen, bevor man versucht, direkt zu verkaufen. Die Formel lautet: erst Mehrwert bieten, dann konvertieren.</p>



<p><strong>4. Strukturierte Profile und optimierte Bios</strong></p>



<p>Eine gut gestaltete Instagram-Bio ist der erste Eindruck, den ein Besucher bekommt. Sie sollte klar und überzeugend sein, mit einem ansprechenden Foto, einem aussagekräftigen Profilnamen und einer deutlichen Handlungsaufforderung. Caroline Flett und Whitney Bartlette gaben praktische Tipps, wie man die Bio so gestaltet, dass sie gleich Interesse weckt.</p>



<p><strong>5. Unterhaltung schlägt Werbung</strong></p>



<p>Greg Fass von Liquid Death zeigte, dass humorvolle und unterhaltsame Inhalte oft viel besser ankommen als klassische Werbung. Sein Rat: Zeig dein Produkt, ohne zu direkt zu verkaufen. Die Marke wurde erfolgreich, indem sie auf originelle und witzige Ideen setzte, die sich von Standard-Marketing abheben.</p>



<p><strong>6. Schnelle Reaktionen und relevante Angebote</strong></p>



<p>Stephanie Perozo Bello erklärte, dass schnelle Antworten (innerhalb von 5 Minuten) die Conversion-Rate drastisch erhöhen können. Es geht darum, Nutzer direkt abzuholen, sei es mit kostenlosen Inhalten, Angeboten oder schnellen Follow-ups. Solche Strategien halten die Zielgruppe aktiv und steigern das Vertrauen.</p>



<h4 class="wp-block-heading"><strong>Event-Format und Plattform: Flexibilität und Vernetzung</strong></h4>



<p>Das Online-Format des Summits und die benutzerfreundliche Event-Plattform machten es für alle Teilnehmer einfach, sich Vorträge anzuschauen – entweder live oder später als Aufzeichnung. Besonders hilfreich waren die virtuellen Konferenzräume, in denen man sich mit Veranstaltern, Sponsoren, Speakern und anderen Teilnehmern vernetzen konnte. So entstanden viele wertvolle Kontakte und Austauschmöglichkeiten.</p>



<p>Ein besonderes Highlight: Die musikalische Untermalung während der Mittagspausen durch <strong>DJ Graffiti</strong>, der mit seinen energiegeladenen Beats für eine lebendige und motivierte Stimmung sorgte.</p>



<h4 class="wp-block-heading"><strong>Fazit</strong></h4>



<p>Der <strong>Instagram Summit 2024</strong> zeigte, dass Erfolg auf Instagram heute stark auf Automatisierung, KI-gestützte Tools und durchdachte Community-Strategien setzt. Egal ob Marke, Creator oder Social-Media-Manager – wer diese Trends aufgreift, kann Reichweite und Engagement auf authentische Weise steigern. Das Event war nicht nur informativ, sondern auch durch das interaktive Online-Format und die spannenden Sessions sehr zugänglich und inspirierend.</p>
<p>The post <a href="https://www.adtraffic.de/instagram-summit-2024-trends-und-highlights-im-ueberblick/">Instagram Summit 2024: Trends und Highlights im Überblick</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>2024 fürs Ehrenamt: Freiwillige Feuerwehr Solln</title>
		<link>https://www.adtraffic.de/2024-fuers-ehrenamt-freiwillige-feuerwehr-solln/</link>
		
		<dc:creator><![CDATA[rs]]></dc:creator>
		<pubDate>Thu, 18 Jan 2024 18:00:58 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<guid isPermaLink="false">https://www.adtraffic.de/?p=1175</guid>

					<description><![CDATA[<p>Die Freiwillige Feuerwehr München Solln hat zum Jahreswechsel eine Geldspende von uns erhalten. Erfahren Sie im nachfolgenden Artikel, wie es dazu kam und wofür die Spendengelder bei der Feuerwehr verwendet werden. Sie retten, löschen, bergen oder schützen und jeder ist im Grunde froh, wenn er sie nicht braucht: Die Feuerwehren. Die Kameradinnen und Kameraden der [&#8230;]</p>
<p>The post <a href="https://www.adtraffic.de/2024-fuers-ehrenamt-freiwillige-feuerwehr-solln/">2024 fürs Ehrenamt: Freiwillige Feuerwehr Solln</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Die Freiwillige Feuerwehr München Solln hat zum Jahreswechsel eine Geldspende von uns erhalten. Erfahren Sie im nachfolgenden Artikel, wie es dazu kam und wofür die Spendengelder bei der Feuerwehr verwendet werden.</p>



<p>Sie retten, löschen, bergen oder schützen und jeder ist im Grunde froh, wenn er sie nicht braucht: Die Feuerwehren. Die Kameradinnen und Kameraden der insgesamt 21 Abteilungen der Freiwilligen Feuerwehren in München sorgen gar ehrenamtlich für unsere Sicherheit. Und das rund um Uhr. Allein die Abteilung Solln wird zu bis zu 120 Einsätzen pro Jahr alarmiert.</p>



<p>Unser Kollege Hannes ist schon lange Mitglied der Sollner Feuerwehr und hat im Sommer 2023 erfolgreich die Ausbildung zum Zugführer absolviert. Seinen Urlaubsantrag für den zweiwöchigen Lehrgang haben wir nach kurzer interner Rücksprache abgelehnt. Wir wollten nicht, dass Hannes seinen Erholungsurlaub für diese Fortbildung in seiner ehrenamtlichen Tätigkeit opfert. Deshalb haben wir ihn für die zwei Wochen freigestellt und seine Vertretung unter uns aufgeteilt.</p>



<p>Arbeitgeber können für solche Fälle einen sogenannten &#8220;Antrag auf Erstattung der fortgewährten Leistungen im Zusammenhang mit dem Feuerwehrdienst oder dem Dienst im Katastrophenschutz&#8221; einreichen. Unser Antrag wurde von der Stadt München zügig bearbeitet und bewilligt, was uns eine unverhoffte Ausgleichszahlung beschert hat.</p>



<p>Diese Zahlung und den Jahreswechsel haben wir zum Anlass genommen, der Freiwilligen Feuerwehr Solln eine Geldspende in Höhe von 2.024 Euro zukommen zu lassen. Solche Spenden verwenden die freiwilligen Feuerwehren beispielsweise zur Aufklärung und Brandschutzerziehung oder auch zur Ergänzung der technischen Ausrüstung. So haben in den letzten Jahren unter anderem ein elektrischer Lüfter und das Sperrwerkzeug ihren Weg ins Hilfeleistungslöschgruppenfahrzeug (HLF) der Sollner Feuerwehr gefunden. Auch für die Öffentlichkeitsarbeit, Anwerbung von neuen Mitgliedern und zur Unterstützung der Jugendfeuerwehren können solche Gelder verwendet werden.</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="768" src="https://www.adtraffic.de/wp-content/uploads/adtraffic-FF-Solln-4x3-72dpi-1024x768.jpg" alt="" class="wp-image-1180" srcset="https://www.adtraffic.de/wp-content/uploads/adtraffic-FF-Solln-4x3-72dpi-1024x768.jpg 1024w, https://www.adtraffic.de/wp-content/uploads/adtraffic-FF-Solln-4x3-72dpi-300x225.jpg 300w, https://www.adtraffic.de/wp-content/uploads/adtraffic-FF-Solln-4x3-72dpi-768x576.jpg 768w, https://www.adtraffic.de/wp-content/uploads/adtraffic-FF-Solln-4x3-72dpi.jpg 1080w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>Am 16.01.2024 hat unser Geschäftsführer Richard Stinauer (1.v.r.) im Sollner Feuerwehrhaus unseren Spendenscheck offiziell an den Vorstand des Fördervereins der Freiwilligen Feuerwehr Solln übergeben, der auch fast vollzählig anwesend war: Der Vorsitzende und Abteilungskommandant Christian Kindermann (3.v.l.), sein erster stellvertretender Vorsitzender und stellvertretender Abteilungskommandant David Plath (2.v.r.), Kassier Hannes Eifler (1.v.l.) und Schriftführerin Julia Holzheu (2.v.l.) haben sich sehr über die Zuwendung gefreut, die in dieser Form bislang offenbar ein Einzelfall ist.</p>



<p>Um das zu ändern, haben wir gemeinsam beschlossen, mit Beiträgen sowohl auf Seiten der Freiwilligen Feuerwehr Solln (<a href="https://www.feuerwehr-solln.de/">Webseite</a> / <a href="https://www.instagram.com/feuerwehr.solln/">Instagram</a> / <a href="https://www.facebook.com/feuerwehr.solln">Facebook</a>) als auch auf unseren Seiten etwas die Werbetrommel für derartige Zuwendungen zu rühren. Für Fragen zum Prozedere stehen wir gerne zur Verfügung.</p>
<p>The post <a href="https://www.adtraffic.de/2024-fuers-ehrenamt-freiwillige-feuerwehr-solln/">2024 fürs Ehrenamt: Freiwillige Feuerwehr Solln</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Vorstellung des GA4 Tracking Logger</title>
		<link>https://www.adtraffic.de/ga4-tracking-logger-chrome-developer-toolsextension-panel/</link>
		
		<dc:creator><![CDATA[pp_admin]]></dc:creator>
		<pubDate>Mon, 21 Aug 2023 08:50:40 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<guid isPermaLink="false">https://www.adtraffic.de/?p=469</guid>

					<description><![CDATA[<p>Der GA4 Tracking Logger ist eine leistungsstarke Chrome Erweiterung, die das Verfolgen und Protokollieren von Google Analytics Tracking-Aufrufen vereinfacht.</p>
<p>The post <a href="https://www.adtraffic.de/ga4-tracking-logger-chrome-developer-toolsextension-panel/">Vorstellung des GA4 Tracking Logger</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Bist du ein Webentwickler oder Digital Marketer, der mit Google Analytics arbeitet? Das Verfolgen einzelner Tracking-Aufrufe auf Webseiten kann entscheidend sein, um das Nutzerverhalten zu verstehen und die Leistung der Website zu verbessern. Wir stellen vor: Der GA4 Tracking Logger – eine leistungsstarke Erweiterung der Chrome Developer Tools, die das Verfolgen und Protokollieren von Google Analytics Tracking-Aufrufen vereinfacht.</p>



<h3 class="wp-block-heading">Los geht’s</h3>



<p>Um loszulegen, kannst du den Erweiterungscode von unserem&nbsp;<a href="https://github.com/RicSti/ga4-tracking-logger-chrome-extension-panel">GitHub-Repository</a>&nbsp;herunterladen. Das Repository enthält auch eine&nbsp;<a href="https://github.com/RicSti/ga4-tracking-logger-chrome-extension-panel/blob/main/README.md">Installationsanleitung</a>, die dir bei der Einrichtung der Erweiterung in deinem Chrome-Browser hilft.</p>



<h3 class="wp-block-heading">GA4 Tracking-Aufrufe loggen leicht gemacht</h3>



<p>Der GA4 Tracking Logger fügt deinen Chrome Developer Tools ein benutzerdefiniertes Panel hinzu. Damit kannst du ganz einfach Google Analytics Tracking-Aufrufe auf der untersuchten Webseite überwachen und protokollieren. Ob du gerade eine Website testest, Probleme behebst oder das Nutzerverhalten analysierst – diese Erweiterung vereinfacht in jedem Fall das Erfassen wertvoller Tracking-Daten.</p>



<h3 class="wp-block-heading">Wichtige Funktionen für effektives Tracking</h3>



<ol class="wp-block-list">
<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color"><strong>Starten und Beenden des Loggers</strong><br></mark>Mit einem Klick kannst du die Verfolgung von Tracking-Aufrufen starten und stoppen.</li>



<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color"><strong>Stapelverarbeitung von URLs</strong> <br></mark>Du kannst mehrere URLs als Liste eingeben. Das Tool verarbeitet sie nacheinander und erfasst die Google Analytics Tracking-Aufrufe innerhalb der ersten fünf Sekunden.</li>



<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color"><strong>Export von geloggten Ereignissen</strong><br></mark>Nach dem Loggen kannst du die erfassten Tracking-Ereignisse als CSV-Datei exportieren und analysieren. Diese Funktion erleichtert die Analyse und den Austausch der gesammelten Daten.</li>
</ol>



<h3 class="wp-block-heading">So funktioniert der GA4 Tracking Logger</h3>



<p>Die Erweiterung erfasst Tracking-Aufrufe, die spezifische URL-Muster enthalten, automatisch und protokolliert die relevanten Daten. Diese Daten werden mit Zeitstempeln versehen, um sicherzustellen, dass du eine genaue Aufzeichnung hast. Mit einer benutzerfreundlichen Oberfläche und intuitiven Steuerelementen vereinfacht die Erweiterung den Prozess der Erfassung und Protokollierung, um dir Zeit und Aufwand zu sparen.</p>



<h3 class="wp-block-heading">Fazit</h3>



<p>Mit dem GA4 Tracking Logger hast du ein leistungsstarkes Werkzeug zur Hand, um das Verfolgen und Protokollieren von Google Analytics Tracking-Aufrufen zu vereinfachen. Diese Erweiterung vereinfacht den Prozess und liefert dir wertvolle Einblicke in das Nutzerverhalten und die Interaktion. Ob Entwickler, Marketer oder Analyst – dieses Tool kann deine Arbeitsweise verbessern und dir helfen, fundierte Entscheidungen auf Grundlage genauer Tracking-Daten zu treffen. Lade die Erweiterung herunter und beginne noch heute, deine Google Analytics Tracking-Daten optimal zu nutzen.</p>



<h2 class="wp-block-heading"></h2>
<p>The post <a href="https://www.adtraffic.de/ga4-tracking-logger-chrome-developer-toolsextension-panel/">Vorstellung des GA4 Tracking Logger</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Dein Erstes Google Ads Script</title>
		<link>https://www.adtraffic.de/dein-erstes-google-ads-script/</link>
		
		<dc:creator><![CDATA[pp_admin]]></dc:creator>
		<pubDate>Fri, 24 Mar 2023 13:28:33 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<guid isPermaLink="false">https://www.adtraffic.de/?p=106</guid>

					<description><![CDATA[<p>Erfahre anhand eines konkreten Beispiels, wie Du Dir auch ohne fundierte Programmierkenntnisse mit überschaubarem Zeitaufwand eine individuelle Automatisierungslösung für Deine Google Ads Kampagnen selbst bauen kannst.</p>
<p>The post <a href="https://www.adtraffic.de/dein-erstes-google-ads-script/">Dein Erstes Google Ads Script</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Erfahre anhand eines konkreten Beispiels, wie Du Dir auch ohne fundierte Programmierkenntnisse mit überschaubarem Zeitaufwand eine individuelle Automatisierungslösung für Deine Google Ads Kampagnen selbst bauen kannst. Grundkenntnisse in JavaScript solltest Du idealerweise mitbringen.</p>


<div class="lazyblock-inhaltsverzeichnis-anker-Z28z9IC wp-block-lazyblock-inhaltsverzeichnis-anker">    <a id="vorwort" class="anchor"></a></div>


<h2 class="wp-block-heading">Vorwort</h2>



<h3 class="wp-block-heading" id="google_ads_scripts">Google Ads Scripts</h3>



<p>Jenseits von Filtern, Regeln und Bulk-Uploads bieten Dir Google Ads Scripts eine ungleich größere Auswahl an Möglichkeiten, die Prozesse bei der Überwachung und Optimierung Deiner Google Ads Kampagnen zu automatisieren. Auf der zugehörigen&nbsp;<a href="https://developers.google.com/google-ads/scripts/docs/start">Developers Seite</a>&nbsp;findest Du eine Einführung (Guides) und die Referenz (Reference) zu Google Ads Scripts, sowie viele Code-Beispiele (Examples) für einzelne Funktionen bzw. Abfragen und sogar einige fertige Komplettlösungen (Solutions). Letztere sind in der Regel einfach konfigurierbar und lassen sich so relativ leicht den jeweiligen Bedürfnissen anpassen.</p>



<h3 class="wp-block-heading">Dein individuelles Problem</h3>



<p>Die vorgenannten Beispiele decken schon eine ganze Reihe an Anwendungsfällen ab oder lassen sich durch mehr oder weniger geringfügige Änderungen entsprechend anpassen. Oft sind die Vorlagen aber doch zu weit weg von der eigentlich gewünschten Lösung. Das ist der Zeitpunkt, selbst Hand anzulegen und ein neues, eigenes Google Ads Script – sozusagen auf der grünen Wiese – zu erstellen.</p>



<h3 class="wp-block-heading">Unser konkretes Beispiel</h3>



<p>Google legt die Anzeigenausrichtung nach Standort und Sprache bekanntlich relativ flexibel aus:</p>



<figure class="wp-block-pullquote"><blockquote><p><em>Das Language Targeting erlaubt es, User zu targeten, die der jeweiligen Sprache mit</em> <em>sehr hoher Wahrscheinlichkeit mächtig sind. Hierzu verwenden wir unter anderem die</em> <em>gewünschte Sprache des Users bei Youtube, den Standort und die Browsereinstellung.</em></p></blockquote></figure>



<p>Dadurch werden selbst bei sehr eingeschränkter regionaler Ausrichtung die Anzeigen auch auf fremdsprachigen Seiten mit ausländischen Top-Level-Domains ausgespielt, die in unserem Fall erwartungsgemäß schlechte Performance-Daten aufweisen.</p>


<div class="lazyblock-inhaltsverzeichnis-anker-Z9EeXs wp-block-lazyblock-inhaltsverzeichnis-anker">    <a id="die-idee" class="anchor"></a></div>


<h2 class="wp-block-heading">Die Idee</h2>



<p>Der Impuls für die Entwicklung einer Automatisierung kommt naturgemäß meistens aus dem operativen Account Management. Unser Kollege Robert erklärt im Interview, wie sich aus seinem Wunsch nach einer Lösung für sein konkretes Problem das Skript aus diesem Artikel entwickelt hat.</p>



<p><em><strong>Richard</strong>:</em>&nbsp;Hi Robert, kannst Du noch einmal kurz zusammenfassen, wie die Idee für eine automatisierte Lösung zum Ausschluss von Placements zustande gekommen ist?</p>



<p class="has-secondary-color has-text-color"><em><strong>Robert</strong>:</em>&nbsp;Die Antwort ist relativ einfach: aus dem täglichen Doing heraus. Als Account-Manager war mir beim Reporting einiger neuer Display-Kampagnen in einem unserer Kunden-Accounts aufgefallen, dass besonders viele und auf den ersten Blick doch eher unpassende Placements im Report “Wo Anzeigen ausgeliefert wurden” aufgeführt wurden. So hatten sich auf der ersten Seite des Berichts eine Vielzahl an Placements mit Endungen wie .ru, .pl oder .hu angehäuft – Placements bzw. Domainendungen also, die zumindest zu einem guten Teil an der eigentlich adressierten Zielgruppe vorbeigehen dürften.</p>



<p><em><strong>Richard</strong>:</em>&nbsp;Hattest Du noch weitere Anhaltspunkte dafür, dass die besagten Placements eher ungeeignet sind, einmal abgesehen vom Umstand mit den unpassenden Top-Level-Domains?</p>



<p class="has-secondary-color has-text-color"><em><strong>Robert</strong>:&nbsp;</em>Ja, tatsächlich war mir bei einem genaueren Blick auf einige der Placements auch deren konkrete Performance negativ aufgefallen. Dazu ein Beispiel:</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh4.googleusercontent.com/_0kbTU_WxcXgaqG9HWz8k9uB_rsCXGoQxh12em8_lNYT7259MqDp9IXcFlMhQSz34cwLMxO3lIsiALLBAo29RHlFiJkdNsj538-Z7jMFBE2_KMMBCTJG7n7vhNbysRdOj1AvmDzB8iApSTDg8RtaT28" alt=""/></figure>



<p class="has-secondary-color has-text-color">Dieses Placement ist auch in anderen Display-Kampagnen immer wieder aufgetaucht und hatte dabei ähnlich “verdächtige” Kennzahlen ausgewiesen. Bei einer CTR von über 50% im Display-Netzwerk hatten hier bei mir als verantwortlicher Account-Manager sofort die Alarmglocken geläutet und das Placement musste raus.</p>



<p><em><strong>Richard</strong>:</em>&nbsp;Wie ging es dann weiter?</p>



<p class="has-secondary-color has-text-color"><em><strong>Robert</strong>:</em>&nbsp;Ausgehend vom manuellen Placement-Ausschluss und der doch relativ großen Menge potenziell ungeeigneter Placements kam relativ bald die Frage auf, ob sich dieser Prozess denn nicht – zumindest in Teilen – automatisieren ließe. In meiner naiven Vorstellung konnte es doch nicht so schwer sein, Google mitzuteilen, dass wir gerne nur Placements mit Endungen wie beispielsweise .de, .org oder .com drinnen haben und andere eben ausschließen möchten. Der bis zu diesem Zeitpunkt manuell durchgeführte Placement-Ausschluss gestaltete sich vergleichsweise aufwändig, da hier jedes einzelne Placement einzeln eingetragen und bestätigt werden musste. Leider musste ich aber relativ schnell feststellen, dass ein pauschales Ausschließen von ungewünschten TLDs mit Bordmitteln von Google so nicht zu bewerkstelligen war – vermutlich weil auch nicht unbedingt gewünscht. 😉</p>



<p><em><strong>Richard</strong>:</em>&nbsp;Und dann ging es als Nächstes auch schon an die Recherche und ans gemeinsame “Scripten”?</p>



<p class="has-secondary-color has-text-color"><em><strong>Robert</strong>:</em>&nbsp;Richtig. Die Idee war relativ schnell geboren und musste jetzt “nur” noch in ein entsprechendes Google Ads-Script gepackt werden. Dass sich dieses Skript, wenn einmal fertig, dann mit hoher Wahrscheinlichkeit auch gewinnbringend für andere Kunden-Accounts einsetzen ließe, war während des gesamten Prozesses eine schöne, zusätzliche kleine Motivationsspritze.</p>



<p><em><strong>Richard</strong>:</em>&nbsp;Wie zufrieden bist Du mit dem gemeinsamen Ergebnis?</p>



<p class="has-secondary-color has-text-color"><em><strong>Robert</strong>:</em>&nbsp;Sehr zufrieden. Insbesondere auch deshalb, weil sich an die erste Version des Skripts sehr schnell eine zweite angeschlossen hat, die die erste direkt noch um eine Funktion für ein Whitelisting bestimmter, erwünschter Placements erweitert hat.</p>



<p><em><strong>Richard</strong>:</em>&nbsp;Könntest Du noch kurz erklären, was es damit auf sich hat?</p>



<p class="has-secondary-color has-text-color"><em><strong>Robert</strong>:&nbsp;</em>Nach ca. einer Woche Arbeit mit der ersten Version des Skripts hat sich – erneut aus dem täglichen Doing heraus – schnell noch ein relativ wichtiger Punkt herauskristallisiert: es gibt eben doch auch Placements, die nicht auf die vertrauten TLDs enden, die aber dennoch bespielt werden sollen (ein schönes Beispiel dazu: “bedienungsanleitu.ng” – vermutlich schon einmal dem ein oder der anderen begegnet). So war also relativ schnell klar – wir brauchen eine Whitelisting-Funktion, um bestimmte Placements dauerhaft von einem automatischen Ausschluss ausnehmen zu können.</p>



<p><em><strong>Richard</strong>:</em>&nbsp;In drei Stichpunkten – was waren Deine wichtigsten Learnings aus dem gesamten Prozess?</p>



<p class="has-secondary-color has-text-color"><em><strong>Robert</strong>:&nbsp;</em>(1) Die Erstellung von Google Ads-Scripts folgt einer interessanten Mischung aus gesundem Menschenverstand und purer Logik. (2) Grundlegende JavaScript-Kenntnisse vereinfachen die Erstellung zweifellos, man ist aufgrund der umfangreichen und ausführlichen Google-Dokumentation aber auch ohne solche Kenntnisse nicht komplett aufgeschmissen. (3) Google Ads-Scripts möchten sich von sich aus gerne “weiterentwickeln”, man muss ihnen nur ein wenig dabei behilflich sein… 😉</p>



<p><em><strong>Richard</strong>:</em>&nbsp;Vielen Dank für das Interview!</p>


<div class="lazyblock-inhaltsverzeichnis-anker-Z1tcOyc wp-block-lazyblock-inhaltsverzeichnis-anker">    <a id="der-manuelle-prozess" class="anchor"></a></div>


<h2 class="wp-block-heading">Der manuelle Prozess</h2>



<p>Wie Robert im Interview beschrieb, wurden unerwünschte Placements bisher in der Ansicht “Wo Anzeigen ausgeliefert wurden” mittels Filter ausgewählt und als Placement-Ausschlüsse in der jeweiligen Kampagne ergänzt. Ein direktes Hinzufügen dieser Placements aus dieser Ansicht in eine gemeinsame Ausschlussliste ist nicht möglich – sie müssten händisch kopiert oder abgetippt werden.</p>



<h3 class="wp-block-heading">Der Wunsch</h3>



<p>Weil diese marktfremden Placements sinnvolle Ausschlüsse für mehrere, wenn nicht alle Kampagnen sind, sollten diese automatisiert in einer gemeinsamen Placement-Ausschlussliste gepflegt werden, die für alle betreffenden Kampagnen angewendet wird.</p>



<h3 class="wp-block-heading">Die Lösung</h3>



<p>Um die konkreten Anforderungen für unser eigenes Google Ads Script zu definieren, überlegen wir zunächst, wie wir den Prozess in einzelne Schritte zerlegen können:</p>



<h4 class="wp-block-heading">Vorbereitung: Placement Ausschlussliste erstellen und für Kampagne(n) anwenden</h4>



<p>Auch das könnte man automatisieren, wir haben uns aber dazu entschieden, diese Einmalaufgabe manuell zu erledigen.</p>



<ol class="wp-block-list">
<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color"><strong>Unerwünschte Placements erkennen<br></strong></mark>Das Script soll zuerst eine Liste mit den Placements erstellen, die als Ausschluss in Frage kommen.</li>



<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color"><strong>In Ausschlussliste ergänzen<br></strong></mark>Sofern die unerwünschten Placements noch nicht ausgeschlossen sind, sollen sie in der Ausschlussliste ergänzt werden.</li>



<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color"><strong>Bestätigung per E-Mail verschicken<br></strong></mark>Nach der Ausführung soll das Script eine E-Mail mit den ausgeschlossenen Placements an den zuständigen Account Manager verschicken.</li>
</ol>


<div class="lazyblock-inhaltsverzeichnis-anker-1dsgaX wp-block-lazyblock-inhaltsverzeichnis-anker">    <a id="die-recherche" class="anchor"></a></div>


<h2 class="wp-block-heading">Die Recherche</h2>



<p>Für jeden Prozessschritt werden wir eine Funktion oder Abfrage benötigen. Im Vorfeld recherchieren wir deshalb, welche Objekte innerhalb der Google Ads Script API dafür in Frage kommen:</p>



<ol class="wp-block-list">
<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color"><strong>Unerwünschte Placements erkennen<br></strong></mark>Zur Abfrage von Daten aus Google Ads hält die API die Methode <a href="https://developers.google.com/google-ads/scripts/docs/reference/adsapp/adsapp#search_2">search(query, optArgs)</a> bereit.<br>Die Abfragen kann man in der <a href="https://developers.google.com/google-ads/api/docs/query/overview">Google Ads Query Language</a> schreiben.<br>Damit können eine ganze Menge an <a href="https://developers.google.com/google-ads/api/fields/v12/overview">Datenquellen und -feldern</a> abgefragt werden.<br>Und es gibt einen <a href="https://developers.google.com/google-ads/api/fields/v12/overview_query_builder">Google Ads Query Builder</a>, um diese Abfragen zu bauen.<br>Auf den ersten Blick kommen drei Ressourcen für unsere Aufgabe in Frage:
<ul class="wp-block-list">
<li><a href="https://developers.google.com/google-ads/api/fields/v12/detail_placement_view_query_builder">Detail Placement View</a></li>



<li><a href="https://developers.google.com/google-ads/api/fields/v12/group_placement_view_query_builder">Group Placement View</a></li>



<li><a href="https://developers.google.com/google-ads/api/fields/v12/managed_placement_view_query_builder">Managed Placement View</a></li>
</ul>
</li>



<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color"><strong>In Ausschlussliste ergänzen<br></strong></mark>In der Google Ads Script API gibt es ein offenbar passendes Objekt mit der Bezeichnung <a href="https://developers.google.com/google-ads/scripts/docs/reference/adsapp/adsapp_excludedplacementlist">AdsApp.​Excluded Placement List,</a> mit dessen Methoden addExcludedPlacement und addExcludedPlacements einzelne oder auch mehrere Placements gleichzeitig zu einer Placement-Ausschlussliste hinzugefügt werden können.</li>



<li><mark style="background-color:rgba(0, 0, 0, 0)" class="has-inline-color has-secondary-color"><strong>Bestätigung per E-Mail verschicken<br></strong></mark>Unter den Code-Beispielen auf der Google Ads Scripts Seite findet sich unter <a href="https://developers.google.com/google-ads/scripts/docs/examples/mailapp">Utilities > MailApp</a> das Snippet “Send a simple email”, das offenbar genau diesen Zweck erfüllt.<br></li>
</ol>


<div class="lazyblock-inhaltsverzeichnis-anker-1NpGkg wp-block-lazyblock-inhaltsverzeichnis-anker">    <a id="die-erstellung" class="anchor"></a></div>


<h2 class="wp-block-heading">Die Erstellung</h2>



<p>Nach Abschluss unserer Recherche können wir direkt mit der Erstellung des Script-Codes anfangen.</p>



<h3 class="wp-block-heading">Neues Script anlegen</h3>



<p>Dazu legen wir uns zuerst ein neues Skript im betreffenden Google Ads Account an. Zum Bereich “Skripts” gelangt man in Google Ads über die Header-Navigation durch Klicken auf “Tools und Einstellungen &gt; Bulk-Aktionen &gt; Skripts”. Ein neues leeres Skript wird durch Klick auf den blauen Plus-Button und die anschließende Auswahl der Option “Neues Skript” erstellt.</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh6.googleusercontent.com/TgtwNx5BqCIshIK7oAkr-eCSFhvLVXxxC4JgWalW2ShV_hGHXt4sf5dl95oml3NT8g9o-bWnONV4CAxhh13u0rXSCs9HljtFlsf56VHsjACUWdpa3thGzBEPV4b0QOxnOhV19Vbs96y49JS6r-Q-JmA" alt=""/></figure>



<p>Das neu erstellte Skript fordert zunächst eine Autorisierung an, um später Änderungen im Namen des jeweiligen Nutzers vornehmen zu können.</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh3.googleusercontent.com/YazJgGHUdo6--I9KVqBAJzod5sqFd5mPAZM3uCAG8Bo8YyRtgEwzyfVlPyaG6tIRVKM23-1TSHR67g3F9FnpxnS_FQi1nOgcquXT5-x3mRfkWOcD3n3eOXoq0-xyA9LJot6yPqHM8u-tYAxyCFUDa_k" alt=""/></figure>



<p>Nach Klick auf “Autorisieren” kann man zunächst das gewünschte Konto auswählen und dem Skript dann die benötigten Zugriffe erlauben.</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh6.googleusercontent.com/ZLL2DT0qUiCO7VaPek0Yhxf57URiHpAgtEw7x_SCDSd1ru9Ka6dw8wk3dn8XSGiENSWI8b3b-NZfwNHYjxqjSoAEguGkcAePDNR26SBeNULqgfxy7HPu-sEcmbGyF1o6VM4TioAGGadWN4wb0h8xWtU" alt=""/></figure>



<p>Dem Skript kann man auch gleich einen passenden Namen geben.</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh4.googleusercontent.com/4z7wVKfFyquJ1-wh2dGEnCoYI3Xtf-2bNm5855mWIV64e5OqbMucohktz8qGSbGXVEgUpW-jOpNLaM725fgVNHeooUCurXxDtr_qwbHUD_VRISikARFrw1-16IzQT8uG0lx1jhi8OKSo7crOOpcy4nE" alt=""/></figure>



<p>Jetzt kann es losgehen mit der Erstellung des Codes…</p>



<h3 class="wp-block-heading">Funktion queryPlacementUrls()</h3>



<p>Im ersten Schritt möchten wir unerwünschte Placements erkennen. Dazu schreiben wir uns eine Funktion, die uns ein sortiertes Array zurückgibt.</p>



<pre class="wp-block-code"><code>function queryPlacementUrls(){
  var placementUrls = &#91;];
  return placementUrls.sort();
}</code></pre>



<p>Um das Array zu füllen, erstellen wir uns mithilfe des Google Ads Query Builders zunächst den Code zur Abfrage der unerwünschten Placements in unserer/n Display-Kampagne/n.</p>



<p>In unserem Beispiel durchsuchen wir dazu alle aktiven und pausierten Kampagnen vom Typ “DISPLAY”, deren Name mit “GDN_” beginnt und fragen alle Placements vom Typ “WEBSITE” ab, die nicht auf eine der im Suchstring angegebenen Top-Level-Domains enden.</p>



<pre class="wp-block-code"><code>  var query = 
    "SELECT " +
    "  group_placement_view.target_url " +
    "FROM group_placement_view " +
    "WHERE " +
    "  campaign.status IN ('ENABLED', 'PAUSED') " +
    "  AND campaign.advertising_channel_type IN ('DISPLAY') " +
    "  AND group_placement_view.placement_type IN ('WEBSITE') " +
    "  AND group_placement_view.target_url NOT REGEXP_MATCH '.*\.(de|at|ch|com|net|org|info)' " +
    "  AND campaign.name REGEXP_MATCH '^GDN_.*$' " +
    ""
    ;
  var result = AdsApp.search(query, {apiVersion: 'v12'});</code></pre>



<p>Das Ergebnis der Abfrage verarbeiten wir anschließend in einer Schleife und schreiben die URL jedes einzelnen Placements in das vorbereitete Array:</p>



<pre class="wp-block-code"><code>  while (result.hasNext()) {
    var row = result.next();
    if ( placementUrls.indexOf(row&#91;'groupPlacementView']&#91;'targetUrl']) == -1 ) {
      placementUrls.push(row&#91;'groupPlacementView']&#91;'targetUrl']);
    }
  }</code></pre>



<p>Die fertige Funktion sieht in unserem Beispiel wie folgt aus:</p>



<pre class="wp-block-code"><code>function queryPlacementUrls(){
  var placementUrls = &#91;];
  var query = 
    "SELECT " +
    "  group_placement_view.target_url " +
    "FROM group_placement_view " +
    "WHERE " +
    "  campaign.status IN ('ENABLED', 'PAUSED') " +
    "  AND campaign.advertising_channel_type IN ('DISPLAY') " +
    "  AND group_placement_view.placement_type IN ('WEBSITE') " +
    "  AND group_placement_view.target_url NOT REGEXP_MATCH '.*\.(de|at|ch|com|net|org|info)' " +
    "  AND campaign.name REGEXP_MATCH '^GDN_.*$' " +
    ""
    ;
  var result = AdsApp.search(query, {apiVersion: 'v12'});
  while (result.hasNext()) {
    var row = result.next();
    if ( placementUrls.indexOf(row&#91;'groupPlacementView']&#91;'targetUrl']) == -1 ) {
      placementUrls.push(row&#91;'groupPlacementView']&#91;'targetUrl']);
    }
  }
  return placementUrls.sort();
}</code></pre>



<p>Um die Funktion im Skript auszuführen, ergänzen wir den Aufruf innerhalb der Hauptfunktion main(). Den Rückgabewert der Funktion schreiben wir zur späteren Verwendung die Variable “placementUrls”:</p>



<pre class="wp-block-code"><code>function main(){
  var placementUrls = queryPlacementUrls();
}</code></pre>



<h3 class="wp-block-heading">Funktion getExcludedPlacements()</h3>



<p>Bevor wir neue Placements in unserer Placement-Ausschlussliste ergänzen, möchten wir zuerst eine Liste der bereits ausgeschlossenen Placements erstellen, um diese nicht (noch einmal) zu verarbeiten.</p>



<p>Auch diese Funktion bereitet zu Beginn ein leeres Array vor, das anschließend befüllt und danach zurückgegeben wird. Mit der Variable “queryListName” übergeben wir später aus der Hauptfunktion main() heraus den Namen der Placement-Ausschlussliste, die das Skript verwenden soll.</p>



<pre class="wp-block-code"><code>function getExcludedPlacements(queryListName){
  var excludedPlacements = &#91;];
  var sharedExcludedPlacementList = getExcludedPlacementList(queryListName);
  var sharedExcludedPlacementIterator = sharedExcludedPlacementList.excludedPlacements().get();
  while (sharedExcludedPlacementIterator.hasNext()) {
    var sharedExcludedPlacement = sharedExcludedPlacementIterator.next();
    excludedPlacements.push(sharedExcludedPlacement.getUrl());
  }
  return excludedPlacements.sort();
}</code></pre>



<p>Die Funktionsweise ähnelt der vorausgegangen Funktion queryPlacementUrls(), allerdings ist die Datenquelle für die Stapelverarbeitung offenbar keine Abfrage, die mit dem Google Ads Query Builder gebaut wurde, sondern entstammt einer separaten Funktion getExcludedPlacementList().&nbsp;</p>



<p>Diese Hilfsfunktion haben wir uns gebaut, um sie später für die Ergänzung der Placement-Ausschlüsse wiederverwenden zu können. Schauen wir uns kurz die Funktionsweise dieser Hilfsfunktion an:</p>



<h3 class="wp-block-heading">Funktion getExcludedPlacementList()</h3>



<p>Die Funktion bedient sich der Methode excludedPlacementLists() der Google Ads API, mit deren Hilfe man Placement-Ausschlusslisten mit bestimmten Eigenschaften zur weiteren Verwendung innerhalb des Skripts abrufen kann.</p>



<p>In unserem Beispiel holen wir die erste gefundene Ausschlussliste ab und übergeben sie zurück an die aufrufende Funktion.</p>



<pre class="wp-block-code"><code>function getExcludedPlacementList(queryListName){
  var sharedExcludedPlacementList = AdsApp.excludedPlacementLists()
      .withCondition("Name = '" + queryListName + "'").get().next();
  return sharedExcludedPlacementList;
}</code></pre>



<p>In der Hauptfunktion main() setzen wir nun den Namen für die zu verwendende Placement-Ausschlussliste und schreiben das Ergebnis der Funktion getExcludedplacements in die Variable “excludedPlacements”:</p>



<pre class="wp-block-code"><code>function main(){
  var placementUrls = queryPlacementUrls();
  var queryListName = 'Globale Placement-Ausschlüsse';
  var excludedPlacements = getExcludedPlacements(queryListName);
}</code></pre>



<h3 class="wp-block-heading">Funktion loadWhitelist()</h3>



<p>Damit wir bestimmte Placements explizit erlauben können, auch wenn sie nicht auf eine der vordefinierten TLDs enden, haben wir uns eine Whitelist als Google Sheet angelegt, die wir manuell befüllen können. Diese Whitelist laden wir vor der weiteren Verarbeitung ebenfalls in ein Array.</p>



<p>Unschwer erkennbar sind die beiden Funktionsparameter, mit denen wir später die URL unseres Google Sheets und den Namen des darin enthaltenen Sheets mit der Whitelist an die Funktion übergeben.</p>



<pre class="wp-block-code"><code>function loadWhitelist(spreadsheetUrl,sheetName){
  const ss = SpreadsheetApp.openByUrl(spreadsheetUrl);
  const sheet = ss.getSheetByName(sheetName);
  const lastRow = sheet.getLastRow();
  const range = sheet.getRange(1, 1, lastRow);
  const values = range.getValues();
  var returnValues = &#91;];
  for (i=0;i&lt;values.length;i++){
    returnValues.push(values&#91;i]&#91;0]);
  }
  return returnValues;
}</code></pre>



<p>Den Ladevorgang ergänzen wir ebenfalls in der Hauptfunktion main() und definieren zuvor zwei globale Variablen mit den benötigten Werten:</p>



<pre class="wp-block-code"><code>const SPREADSHEET_URL = 'https://docs.google.com/spreadsheets/d/----------/';
const SHEET_NAME = 'placements';

function main(){
  var placementUrls = queryPlacementUrls();
  var queryListName = 'Globale Placement-Ausschlüsse';
  var excludedPlacements = getExcludedPlacements(queryListName);
  var whitelist = loadWhitelist(SPREADSHEET_URL,SHEET_NAME);
}</code></pre>



<h3 class="wp-block-heading">Funktion getToBeExcludedPlacements()</h3>



<p>Im nächsten Schritt ermitteln wir die auszuschließenden Placements. Diese Funktion verarbeitet alle drei zuvor vorbereiteten Listen bzw. Arrays:</p>



<ul class="wp-block-list">
<li>placementUrls – alle vermeintlich unerwünschten Placements</li>



<li>excludedPlacements – alle bereits ausgeschlossenen Placements</li>



<li>whitelist – alle explizit gewünschten Placements</li>
</ul>



<p>Die im Stapel “placementUrls” enthaltenen Placements werden zunächst einzeln gegen die Whitelist geprüft. Ist das jeweilige Placement darin enthalten, wird es ignoriert. Für unsere Bestätigungsmail zählen wir außerdem die in der Whitelist gefundenen Placements mit.</p>



<p>Wenn das Placement nicht auf der Whitelist steht, wird als nächstes geprüft, ob es bereits in der Placement-Ausschlussliste enthalten ist. Falls nicht, wird es im Rückgabe-Array “toBeExcludedPlacements” ergänzt.</p>



<p>Sobald alle Placements gegen die Whitelist geprüft wurden, wird das Rückgabe-Array nebst Whitelist-Zähler an die aufrufende Funktion zurückgegeben.</p>



<pre class="wp-block-code"><code>function getToBeExcludedPlacements(placementUrls,excludedPlacements,whitelist){
  var toBeExcludedPlacements = &#91;];
  var numWhitelisted = 0;
  for (var i=0;i&lt;placementUrls.length;i++){
      if (whitelist.indexOf(placementUrls&#91;i]) != -1){
        numWhitelisted++;
      } else if (excludedPlacements.indexOf(placementUrls&#91;i]) == -1){
          toBeExcludedPlacements.push(placementUrls&#91;i]);
      }
  }
  return &#91;toBeExcludedPlacements.sort(),numWhitelisted];
}</code></pre>



<p>Nach Ergänzung der neuen Funktion in der Hauptfunktion main() sieht der Kopfbereich des Skripts wie folgt aus:</p>



<pre class="wp-block-code"><code>const SPREADSHEET_URL = 'https://docs.google.com/spreadsheets/d/----------/';
const SHEET_NAME = 'placements';

function main(){
  var placementUrls = queryPlacementUrls();
  var queryListName = 'Globale Placement-Ausschlüsse';
  var excludedPlacements = getExcludedPlacements(queryListName);
  var whitelist = loadWhitelist(SPREADSHEET_URL,SHEET_NAME);
  var toBeExcludedPlacements = getToBeExcludedPlacements(placementUrls,excludedPlacements,whitelist);
}</code></pre>



<h3 class="wp-block-heading">Funktion addExcludedPlacement()</h3>



<p>Nachdem wir nun alle zu ergänzenden Placement-Ausschlüsse zusammen haben, brauchen wir sie nur noch zu der bestehenden Placement-Ausschlussliste hinzufügen. Die Funktion dazu ist wieder relativ einfach gehalten.</p>



<p>Sie empfängt neben dem Namen der zu verwendenden Placement-Ausschlussliste auch das Array mit den auszuschließenden Placements, ruft die Ausschlussliste auf und hängt die Placements an.</p>



<pre class="wp-block-code"><code>function addExcludedPlacement(queryListName,toBeExcludedPlacements){
  var sharedExcludedPlacementList = getExcludedPlacementList(queryListName);
  sharedExcludedPlacementList.addExcludedPlacements(toBeExcludedPlacements);
}</code></pre>



<p>Eigentlich wäre unser Skript damit schon fertig. Der Kopfbereich sieht jetzt wie folgt aus:</p>



<pre class="wp-block-code"><code>const SPREADSHEET_URL = 'https://docs.google.com/spreadsheets/d/----------/';
const SHEET_NAME = 'placements';

function main(){
  var placementUrls = queryPlacementUrls();
  var queryListName = 'Globale Placement-Ausschlüsse';
  var excludedPlacements = getExcludedPlacements(queryListName);
  var whitelist = loadWhitelist(SPREADSHEET_URL,SHEET_NAME);
  var toBeExcludedPlacements = getToBeExcludedPlacements(placementUrls,excludedPlacements,whitelist);
  addExcludedPlacement(queryListName,toBeExcludedPlacements&#91;0]);
}</code></pre>



<h3 class="wp-block-heading">Funktion sendConfirmationEmail()</h3>



<p>Damit wir aber auch mitbekommen, welche Placements neu ausgeschlossen wurden, lassen wir uns vom Skript eine Mail mit einer Liste der neu ausgeschlossenen URLs schicken.</p>



<p>Diese Funktion empfängt als Parameter ebenfalls den Namen der Ausschlussliste und das Rückgabe-Array mit der Liste der auszuschließenden Placements und dem Whitelist-Zähler.</p>



<p>Damit bereitet es den Output für die zu erstellende E-Mail vor. Zuerst wird die String-Variable “outputPlacements” zeilenweise mit den URLs der ausgeschlossenen Placements befüllt. Es folgt die Definition der Empfängeradresse(n) und des Betreffs, sowie des E-Mail-Inhalts. An dessen Ende wird die URL-Liste angehängt.</p>



<pre class="wp-block-code"><code>function sendConfirmationEmail(queryListName,toBeExcludedPlacements){
  var outputPlacements = "";
  for (i=0;i&lt;toBeExcludedPlacements&#91;0].length;i++){
      outputPlacements += toBeExcludedPlacements&#91;0]&#91;i] + "\n";
  }
  var eMailAddress = "rs@adtraffic.de";
  var eMailSubject = "Placement Excluder // Mein Account-Name";
  var eMailContent = toBeExcludedPlacements&#91;0].length.toLocaleString("de") + " Placement(s) in Placement-Ausschlussliste " + queryListName + " ergänzt." + "\n" +
      toBeExcludedPlacements&#91;1] + " Placement(s) übersprungen (whitelisted)." + "\n\n" + outputPlacements;
  console.log(eMailContent);
  sendSimpleTextEmail(eMailAddress,eMailSubject,eMailContent)
}</code></pre>



<h3 class="wp-block-heading">Funktion sendSimpleTextEmail()</h3>



<p>Den eigentlichen Versand der fertigen Bestätigungsmail übernimmt diese Hilfsfunktion aus der Google Ads Scripts Bibliothek.</p>



<pre class="wp-block-code"><code>function sendSimpleTextEmail(eMailAddress,eMailSubject,eMailContent) {
  MailApp.sendEmail(eMailAddress,eMailSubject,eMailContent);
  Logger.log("Mail sent.");
}</code></pre>



<p>Und damit ist unser Skript bereit für den Einsatz. Der Kopfbereich sieht jetzt so aus:</p>



<pre class="wp-block-code"><code>const SPREADSHEET_URL = 'https://docs.google.com/spreadsheets/d/----------/';
const SHEET_NAME = 'placements';

function main(){
  var placementUrls = queryPlacementUrls();
  var queryListName = 'Globale Placement-Ausschlüsse';
  var excludedPlacements = getExcludedPlacements(queryListName);
  var whitelist = loadWhitelist(SPREADSHEET_URL,SHEET_NAME);
  var toBeExcludedPlacements = getToBeExcludedPlacements(placementUrls,excludedPlacements,whitelist);
  addExcludedPlacement(queryListName,toBeExcludedPlacements&#91;0]);
  sendConfirmationEmail(queryListName,toBeExcludedPlacements);
}</code></pre>



<h3 class="wp-block-heading">Author/License Header hinzugefügt</h3>



<p>Der Form halber haben wir in unserer Version noch einen Info-Header hinzugefügt.</p>



<pre class="wp-block-code"><code>//            _ _              __  __ _      
//   __ _  __| | |_ _ __ __ _ / _|/ _(_) ___ 
//  / _` |/ _` | __| '__/ _` | |_| |_| |/ __|
// | (_| | (_| | |_| | | (_| |  _|  _| | (__ 
//  \__,_|\__,_|\__|_|  \__,_|_| |_| |_|\___|
//                                           
// Placement Excluder 23.1 (c) 2023 by R. Stinauer &amp; R. Frank
//
// E: info@adtraffic.de | W: www.adtraffic.de</code></pre>



<h3 class="wp-block-heading">Weitere Berechtigungen</h3>



<p>Das Script benötigt für den Zugriff auf das Google Sheet mit der Whitelist und den Versand der Bestätigungsmail noch weitere Berechtigungen, die es spätestens bei der ersten Ausführung abfragt. Die entsprechende Meldung taucht am unteren Rand auf:</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh3.googleusercontent.com/eaniITr2F7JhP7lu_0nLqt0B_fJ7jnEZ-rRq--BBnj0SZBcePPpZRnqNoYNHRGtgZuc5QcSm6iYIaWTFd0qkCl45PdvFV7wb9CppNe2kvXlUd_w8HwhCt3C-v4SP2suhAvFmFGd7wwqGwgtYX3UZ590" alt=""/></figure>



<p>Folgende zusätzliche Berechtigungen werden benötigt:</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh3.googleusercontent.com/2vETN4HZjWG0Re83dTAzUYiZNtxKrWYQKpzJWabOPwdLpD3OiVIvQ68bp5tTnbLnTK5SFV7M4ZneplPrECQ107urByJqLQhrjM4hJQ1WZXbjjxit3oyPJidCm6wcs0pCjtm9Z6e-K3CaW70vCC-JOIw" alt=""/></figure>



<h3 class="wp-block-heading">Zeitplan</h3>



<p>Um das fertige Skript automatisch laufen zu lassen, stellen wir auf der Übersichtsseite die Zeitplanung in der Spalte “Häufigkeit” ein.</p>



<p>In unserem Beispiel lassen wir das Skript jeden Montag zwischen 7 und 8 Uhr laufen.</p>



<figure class="wp-block-image"><img decoding="async" src="https://lh4.googleusercontent.com/xVi_Ri17QkK6k_mg5szZGE7GjEGP2ZvFY6GWgbvhIwQMG0OwQSXFtrzy9qScnQRHoKnMSbyY6Cu4Ke2LITw48itZiDIP8uvG1sYO7zxXyVVeSfkZzRINJ4kSteLXICF6vOi7g3so20OEgRLHXntceN0" alt=""/></figure>


<div class="lazyblock-inhaltsverzeichnis-anker-Z2wB6U2 wp-block-lazyblock-inhaltsverzeichnis-anker">    <a id="zusammenfassung" class="anchor"></a></div>


<h2 class="wp-block-heading">Zusammenfassung</h2>



<p>Automatisierungsmöglichkeiten für Google Ads Kampagnen schlummern hinter den meisten operativen Handgriffen. Wir hoffen, Du hast anhand unseres konkreten Beispiels eine genaue(re) Vorstellung davon bekommen, wie Dich Google Ads Scripts bei Deinen täglichen Aufgaben unterstützen können. Unser Artikel hat Dich hoffentlich auch dazu ermuntert, Dich näher mit Google Ads Scripts zu beschäftigen. Vielleicht hast Du auch schon eine konkrete Idee zum Bau Deiner skript-basierten Lösung für ein individuelles Problem. Wir wünschen Dir viele Freude beim Experimentieren und viel Erfolg mit Deinem ersten Google Ads Script!</p>



<h3 class="wp-block-heading">ChatGPT</h3>



<p>Vielleicht hast Du Dich gerade gefragt: “Kann ich mir das nicht einfach von ChatGPT schreiben lassen?”<br><br>Auf die Frage “Could you create Google Ads scripts using the latest Google Ads API version?” antwortete uns das KI-Netzwerk hilfsbereit, aber zurückhaltend:</p>



<p>“As an AI language model, I can provide you with an overview of how Google Ads scripts could be written using the latest Google Ads API version. However, writing complete and functional scripts is beyond my capabilities as it requires knowledge of specific programming languages and expertise in Google Ads scripting.”</p>



<p>Tatsächlich wendet ChatGPT zur Erstellung von Code-Snippets für Google Ads Scripts teils veraltete API-Syntax an und ergänzt bei Bedarf auch gerne mal erfundene Methoden.</p>



<p>Lass Dir also gerne von ChatGPT helfen, aber probier es doch vorher einmal ohne KI…</p>


<div class="lazyblock-inhaltsverzeichnis-anker-Z2qRVrR wp-block-lazyblock-inhaltsverzeichnis-anker">    <a id="downloads" class="anchor"></a></div>


<h2 class="wp-block-heading">Downloads</h2>



<p>Möchtest Du diesen Artikel lieber als PDF herunterladen? Kein Problem. Die Datei findest Du unter folgendem Link:&nbsp;<a href="https://www.adtraffic.de/wp-content/uploads/adtraffic-Dein-Erstes-Google-Ads-Script-230324.pdf">Dein-Erstes-Google-Ads-Script-230324.pdf</a></p>



<p>Du möchtest den Script-Code in einem Stück herunterladen? Auch kein Problem. Die JS-Datei findest Du in folgendem ZIP-Archiv:&nbsp;<a href="https://www.adtraffic.de/wp-content/uploads/google-ads-script-placement-excluder.js.zip">google-ads-script-placement-excluder.js.zip</a></p>



<p><strong>Happy Scripting!</strong></p>
<p>The post <a href="https://www.adtraffic.de/dein-erstes-google-ads-script/">Dein Erstes Google Ads Script</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Google Ads Script: YouTube Channel Excluder</title>
		<link>https://www.adtraffic.de/google-ads-script-youtube-channel-excluder/</link>
		
		<dc:creator><![CDATA[pp_admin]]></dc:creator>
		<pubDate>Fri, 10 Mar 2023 13:28:10 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<guid isPermaLink="false">https://www.adtraffic.de/?p=104</guid>

					<description><![CDATA[<p>Bei Display und Video Kampagnen nimmt es Google nicht ganz so genau mit der Ausrichtung auf einzelne Sprachen. Nutzer sollen lediglich die in der Kampagne eingestellte Sprache verstehen: “Das Language Targeting erlaubt es, User zu targeten, die der jeweiligen Sprache mit sehr hoher Wahrscheinlichkeit mächtig sind. Hierzu verwenden wir unter anderem die gewünschte Sprache des [&#8230;]</p>
<p>The post <a href="https://www.adtraffic.de/google-ads-script-youtube-channel-excluder/">Google Ads Script: YouTube Channel Excluder</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Bei Display und Video Kampagnen nimmt es Google nicht ganz so genau mit der Ausrichtung auf einzelne Sprachen. Nutzer sollen lediglich die in der Kampagne eingestellte Sprache verstehen:</p>



<p>“Das Language Targeting erlaubt es, User zu targeten, die der jeweiligen Sprache mit sehr hoher Wahrscheinlichkeit mächtig sind. Hierzu verwenden wir unter anderem die gewünschte Sprache des Users bei Youtube, den Standort und die Browsereinstellung.”</p>



<p>Das führt dazu, dass Videoanzeigen häufig in fremdsprachigen Kanälen ausgespielt werden. Möchte man diese YouTube Kanäle händisch ausschließen, benötigt man viel Geduld. Schneller und vor allem automatisiert geht es mit einem Google Ads Script.</p>



<p>Unser nachfolgendes Beispiel Script ermittelt YouTube Kanäle in nicht gewünschten Ländern, auf denen die Videokampagne(n) ausgespielt wurde(n) und schließt sie automatisch in der jeweiligen Kampagne aus.</p>



<h2 class="wp-block-heading">Was macht dieses Script genau?</h2>



<ul class="wp-block-list">
<li><strong>Videokampagnen auswählen<br></strong>Das Script wählt zunächst alle aktiven Videokampagnen aus dem jeweiligen Google Ads Konto aus.</li>



<li><strong>Bestehende Ausschlüsse ermitteln<br></strong>Für jede Kampagne werden zunächst die bereits ausgeschlossenen YouTube Kanäle zum späteren Abgleich geladen.</li>



<li><strong>Bestätigte YouTube Kanäle importieren<br></strong>Aus einer externen Liste lädt das Script alle bereits bestätigten YouTube Kanäle.</li>



<li><strong>Neue YouTube Placements abfragen<br></strong>Anschließend fragt das Script alle aktiven YouTube Placements der jeweiligen Kampagne ab, die bisher nicht bestätigt oder ausgeschlossen wurden.</li>



<li><strong>YouTube Kanalinfos abrufen<br></strong>Zu den ermittelten YouTube Placements ruft das Script nun die jeweiligen Kanalinfos ab.</li>



<li><strong>Neue bestätigte YouTube Kanäle exportieren<br></strong>Alle YouTube Kanäle in gewünschten Ländern werden in die Liste mit bestätigten Kanälen exportiert.</li>



<li><strong>YouTube Kanäle in unerwünschten Ländern ausschließen<br></strong>Alle anderen Kanäle schließt das Script auf Kampagnenebene aus.</li>



<li><strong>Bestätigungs-E-Mail<br></strong>Abschließend versendet das Script eine Übersicht der ausgeschlossenen YouTube Kanäle per E-Mail.</li>
</ul>



<h2 class="wp-block-heading">Das Setup</h2>



<p>Bei diesem Beispiel handelt es sich um ein Single Account Script. Eine MCC Version wird folgen, kann aber auch relativ einfach adaptiert werden. Das Script wird direkt in Google Ads unter Tools &amp; Einstellungen &gt; Bulk-Aktionen &gt; Scripts angelegt.</p>



<p>Die erweiterte API “YouTube” wird benötigt. Für die API-Abrufe fallen Credits an. Mit einem regulären Google Konto hat man pro Tag 10.000 freie Credits. Ein höheres Kontingent muss bei Google beantragt werden.</p>



<p>Das fertige Script muss für den Zugriff auf Drive, Mail und YouTube autorisiert werden.</p>



<h2 class="wp-block-heading">Die Code Bausteine</h2>



<p>Nachfolgend erkläre ich zunächst die einzelnen Bausteine. Der komplette Code kann am Ende des Dokuments eingesehen werden.</p>



<h3 class="wp-block-heading">Einstellungen</h3>



<pre class="wp-block-code"><code>var SPREADSHEET_URL = "INSERT_YOUR_SPREADSHEET_URL";
var SHEET_NAME = "INSERT_YOUR_SPREAD_NAME";
var EMAIL_ADRESSES = "INSERT_YOUR_E-MAIL_ADRESSES"; // comma separated
var allowedCountries = /^DE$/; // Provide RegEx, e.g. /^DE$/ or /^DE|AT|CH$/
var impressionsTimeRange = "LAST_7_DAYS";
var impressionsThreshold = 10;</code></pre>



<p>Das hinterlegte Google Sheet benötigt nur eine Spalte mit einem Beispielwert in der ersten Zeile.</p>



<p>Der Sheet Name dient dazu, falls mehrere solcher Whitelists in einem Google Sheet gespeichert sind.</p>



<p>Es kann eine oder auch mehrere E-Mail-Adressen angegeben werden. Mehrere Adressen bitte mit Komma trennen.</p>



<p>Der Wert für “allowedCountries” muss ein regulärer Ausdruck mit zweistelligen Ländercodes nach ISO 3166-1 Alpha-2 sein.</p>



<p>Die Optionen für “impressionsTimeRange” können einem Wert aus der&nbsp;<a href="https://developers.google.com/google-ads/api/docs/query/date-ranges#date-range" target="_blank" rel="noreferrer noopener">Liste “Predefined date range” der Google Ads API</a>&nbsp;enthalten.</p>



<p>Für “impressionsThreshold” kann man einen Schwellwert eintragen, um nur die reichweitenstärksten YouTube Placements zu verarbeiten und so API Credits zu sparen.</p>



<h3 class="wp-block-heading">Funktion main() – Teil 1</h3>



<pre class="wp-block-code"><code>function main() {
  // Prepare an array for logging purposes
  var allExclusions = &#91;];
  // Fetch all active video campaigns and start iterating
  var videoCampaignIterator = AdsApp.videoCampaigns().withCondition("Status = 'ENABLED'").get();
  while (videoCampaignIterator.hasNext()) {
    var alreadyExcludedYouTubeChannels = &#91;];
    var videoCampaign = videoCampaignIterator.next();
    // Fetch all already excluded YouTube Channels from the processed campaign and store them in an array
    var exludedYoutubeChannelIterator = videoCampaign.videoTargeting().excludedYouTubeChannels().get();
    while (exludedYoutubeChannelIterator.hasNext()) {
      var excludedYouTubeChannel = exludedYoutubeChannelIterator.next();
      alreadyExcludedYouTubeChannels.push(excludedYouTubeChannel.getChannelId());
    }
    // Build a batch with to be excluded YouTube channels
    const toBeExcludedYouTubeChannels = checkYouTubeChannels(videoCampaign.getId(),alreadyExcludedYouTubeChannels);</code></pre>



<p>Wie aus den Kommentaren ersichtlich, werden hier zunächst die aktiven Videokampagnen geladen und die zugehörigen, bereits ausgeschlossenen YouTube Placements abgerufen.</p>



<p>Für jede Kampagne wird dann die Funktion “checkYouTubeChannels” unter Verwendung der jeweiligen Kampagnen ID und dem Array mit bereits ausgeschlossenen Placements aufgerufen.</p>



<h3 class="wp-block-heading">Funktion checkYouTubeChannels() – Teil 1</h3>



<pre class="wp-block-code"><code>function checkYouTubeChannels(campaignId,alreadyExcludedYouTubeChannels){
  // Prepare an array for the return values  
  var toBeExcludedYouTubeChannels = &#91;];
  // Load currently known allowed YouTube Channels from Google Sheet
  var knownAllowedYouTubeChannels = getAllowedYouTubeChannels();</code></pre>



<p>Diese Funktion bereitet zunächst ein leeres Array für die Zwischenspeicherung der Rückgabewerte vor und ruft die Funktion “getAllowedYouTubeChannels” auf, um die bereits bestätigten YouTube Kanäle aus dem externen Google Sheet zu importieren.</p>



<h3 class="wp-block-heading">Funktion getAllowedYouTubeChannels()</h3>



<pre class="wp-block-code"><code>function getAllowedYouTubeChannels(){
  var sheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL).getSheetByName(SHEET_NAME);
  var lastRow = sheet.getLastRow();
  var range = sheet.getRange(1, 1, lastRow);
  var returnValues = &#91;];
  var values = range.getValues();
  for (var row in values) {
    for (var col in values&#91;row]) {
      returnValues.push(values&#91;row]&#91;col]);
    }
  }
  return returnValues;
}</code></pre>



<p>An sich eine sehr einfache Funktion zum Abruf der Daten aus dem Google Sheet. Wichtig ist hierbei, dass die zweidimensionalen “values” am Ende als eindimensionale “returnValues” übergeben werden.</p>



<h3 class="wp-block-heading">Funktion checkYouTubeChannels() – Teil 2</h3>



<pre class="wp-block-code"><code>// Prepare an array for newly identified allowed YouTube Channels to be added to the Google Sheet
  var newAllowedYouTubeChannels = &#91;];
  // Query all YouTube placements of the processed campaign with at least ${impressionsThreshold} impressions within the ${impressionsTimeRange}
  var query = 
    "SELECT detail_placement_view.display_name, detail_placement_view.group_placement_target_url FROM detail_placement_view " +
    "WHERE " +
    "  campaign.id = " + campaignId +
    "  AND segments.date DURING " + impressionsTimeRange +
    "  AND metrics.impressions &gt; " + impressionsThreshold + 
    "  AND detail_placement_view.placement_type IN ('YOUTUBE_VIDEO','YOUTUBE_CHANNEL') " +
    "  AND detail_placement_view.group_placement_target_url IS NOT NULL " +
    "  AND detail_placement_view.group_placement_target_url NOT REGEXP_MATCH '" + alreadyExcludedYouTubeChannels.join("|") + "'" +
    "  AND detail_placement_view.group_placement_target_url NOT REGEXP_MATCH '" + knownAllowedYouTubeChannels.join("|") + "'" +
    ""
    ;
  var result = AdsApp.search(query);
  console.log(result.totalNumEntities() + " YouTube Placements found.");
  while (result.hasNext()) {
    var row = result.next();
    const channelId = row&#91;'detailPlacementView']&#91;'groupPlacementTargetUrl'].match(/^.*\/(&#91;^\/]*)$/)&#91;1];
    const channelName = row&#91;'detailPlacementView']&#91;'displayName'];
    const channelInfo = getChannelInfo(channelId); // &#91; Country, Default Language ]</code></pre>



<p>Zurück in der Funktion “checkYouTubeChannels” ruft das Script nun alle YouTube Placements der jeweiligen Kampagne ab, die den Kriterien unter “Einstellungen” entsprechen und bisher weder bestätigt noch ausgeschlossen wurden. Bei der Iteration der daraus resultierenden Ergebnisse werden dann mithilfe der Funktion “getChannelInfo” die Daten von dem YouTube Data API abgefragt.</p>



<h3 class="wp-block-heading">Funktion getChannelInfo()</h3>



<pre class="wp-block-code"><code>function getChannelInfo(channelId){
  try {
    const results = YouTube.Channels.list('snippet,localizations', {
      id: channelId,
      maxResults: 1
    });
    if (results === null) {
      console.log(`ID ${channelId}: Unable to search videos`);
      return;
    }
    return &#91; results.items&#91;0].snippet.country, results.items&#91;0].snippet.defaultLanguage ];
  } catch (err) {
    // TODO (developer) - Handle exceptions from Youtube API
    console.log(`ID ${channelId}: Failed with an error: %s`, err.message);
  }  
}</code></pre>



<p>Diese ebenfalls sehr einfach gehaltene Funktion ruft lediglich das eingestellte Land und die eingestellte Standardsprache für den jeweiligen YouTube Kanal ab und gibt die Werte als Mini-Array zurück.</p>



<h3 class="wp-block-heading">Funktion checkYouTubeChannels() – Teil 3</h3>



<pre class="wp-block-code"><code>    if ( channelInfo &amp;&amp; channelInfo&#91;0]){
      if (channelInfo&#91;0].match(allowedCountries) &amp;&amp; knownAllowedYouTubeChannels.indexOf(channelId) == -1 &amp;&amp; newAllowedYouTubeChannels.indexOf(channelId) == -1){
        // Store channel id of newly identified German YouTube Channel in array to be added to Google Sheet
        newAllowedYouTubeChannels.push(channelId);
      }
      else if (!channelInfo&#91;0].match(allowedCountries)){
        if ( alreadyExcludedYouTubeChannels.indexOf(channelId) == -1){
          toBeExcludedYouTubeChannels.push(
            {
              id: channelId,
              name: channelName,
              country: channelInfo&#91;0],
              language: channelInfo&#91;1]
            }
          );
        }
      }
    }
  }</code></pre>



<p>Basierend auf den zurückgegebenen Kanalinfos wird die Kanal ID des jeweils verarbeiteten Placements entweder für den Export in die Liste bestätigter Kanäle zwischengespeichert oder in den Stapel zum späteren Ausschluss geschrieben.</p>



<h3 class="wp-block-heading">Funktion checkYouTubeChannels() – Teil 4</h3>



<pre class="wp-block-code"><code>if (newAllowedYouTubeChannels.length &gt; 0){
    saveAllowedYouTubeChannels(newAllowedYouTubeChannels);
    newAllowedYouTubeChannels.length.toLocaleString("de") + " new allowed Channel(s) found." + "\n\n";
  }
  return toBeExcludedYouTubeChannels.sort();
}</code></pre>



<p>Der Export in die Liste bestätigter YouTube Kanäle erfolgt unmittelbar. Der Stapel mit den auszuschließenden YouTube Kanälen pro Kampagne wird als Array an die Funktion “main” zurückgegeben.</p>



<h3 class="wp-block-heading">Funktion saveAllowedYouTubeChannels()</h3>



<pre class="wp-block-code"><code>function saveAllowedYouTubeChannels(newAllowedYouTubeChannels){
  var sheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL).getSheetByName(SHEET_NAME);
  var lastRow = sheet.getLastRow();
  var range = sheet.getRange(lastRow+1,1,newAllowedYouTubeChannels.length);
  var outputValues = &#91;];
  while(newAllowedYouTubeChannels.length) outputValues.push(newAllowedYouTubeChannels.splice(0,1));
  range.setValues(outputValues);
  sheet.sort(1);
}</code></pre>



<p>Auch diese Funktion ist sehr einfach gehalten. Sehr hilfreich ist die knappe while/push/slice Schleife, um die eindimensionale Liste mit Kanal IDs in das erforderliche zweidimensionale Ausgabeformat für Google Sheets zu bekommen.</p>



<h3 class="wp-block-heading">Funktion main() – Teil 2</h3>



<pre class="wp-block-code"><code>    // Exclude all YouTube channels in batch from campaign
    for (i=0;i&lt;toBeExcludedYouTubeChannels.length;i++){
      videoCampaign.videoTargeting().newYouTubeChannelBuilder().withChannelId(toBeExcludedYouTubeChannels&#91;i].id).exclude();
    }
    // Add logging information to log array
    allExclusions.push({ campaign: videoCampaign.getName(), excludedYouTubeChannels: toBeExcludedYouTubeChannels })
  }
  // Prepare and send a notification email with logging information
  sendConfirmationEmail(allExclusions);
}</code></pre>



<p>Zurück in der “main” Funktion arbeitet das Script den Stapel mit auszuschließenden YouTube Kanälen ab und ergänzt diese in der jeweiligen Kampagne. Anschließend ruft es die Funktion “sendConfirmationEmail” mit den zuvor aufbereiteten Logging-Daten auf, um die Bestätigungs-E-Mail zu versenden.</p>



<h3 class="wp-block-heading">Funktion sendConfirmationEmail()</h3>



<pre class="wp-block-code"><code>function sendConfirmationEmail(allExclusions){
  var output = "";
  for (i=0;i&lt;allExclusions.length;i++){
    output += allExclusions&#91;i].excludedYouTubeChannels.length.toLocaleString("de") + " Channel(s) excluded from Campaign " + allExclusions&#91;i].campaign + "\n\n";
    var outputChannels = "";
    for (j=0;j&lt;allExclusions&#91;i].excludedYouTubeChannels.length;j++){
        outputChannels += allExclusions&#91;i].excludedYouTubeChannels&#91;j].name + " (" + allExclusions&#91;i].excludedYouTubeChannels&#91;j].country + "|" + allExclusions&#91;i].excludedYouTubeChannels&#91;j].language + ")\n";
        outputChannels += "https://youtube.com/channel/" + allExclusions&#91;i].excludedYouTubeChannels&#91;j].id + "\n\n";
    }
    output += outputChannels;
  }  
  var eMailAddress = EMAIL_ADRESSES;
  var eMailSubject = "YouTube Channel Excluder";
  var eMailContent = output;
  console.log(output);
  sendSimpleTextEmail(eMailAddress,eMailSubject,eMailContent)
}</code></pre>



<p>Diese Funktion bereitet nun noch den Inhalt für die Bestätigungs-E-Mail auf und verschickt sie anschließend mit der einfachen Hilfsfunktion “sendSimpleTextEmail” an die hinterlegten E-Mail-Adressen.</p>



<h3 class="wp-block-heading">Hilfsfunktion sendSimpleTextEmail()</h3>



<pre class="wp-block-code"><code>function sendSimpleTextEmail(eMailAddress,eMailSubject,eMailContent) {
  MailApp.sendEmail(eMailAddress,eMailSubject,eMailContent);
  Logger.log("Mail sent.");
}</code></pre>



<p>Kein Kommentar. 🙂</p>



<h2 class="wp-block-heading">Der vollständige Code</h2>



<p>Happy Copy &amp; Pasting! Und viel Erfolg bei der Optimierung Eurer Google Ads Video Kampagnen!</p>



<pre class="wp-block-code"><code>var SPREADSHEET_URL = "INSERT_YOUR_SPREADSHEET_URL";
var SHEET_NAME = "INSERT_YOUR_SPREAD_NAME";
var EMAIL_ADRESSES = "INSERT_YOUR_E-MAIL_ADRESSES"; // comma separated
var allowedCountries = /^DE$/; // Provide RegEx, e.g. /^DE$/ or /^DE|AT|CH$/
var impressionsTimeRange = "LAST_7_DAYS";
var impressionsThreshold = 10;

function main() {
  // Prepare an array for logging purposes
  var allExclusions = &#91;];
  // Fetch all active video campaigns and start iterating
  var videoCampaignIterator = AdsApp.videoCampaigns().withCondition("Status = 'ENABLED'").get();
  while (videoCampaignIterator.hasNext()) {
    var alreadyExcludedYouTubeChannels = &#91;];
    var videoCampaign = videoCampaignIterator.next();
    // Fetch all already excluded YouTube Channels from the processed campaign and store them in an array
    var exludedYoutubeChannelIterator = videoCampaign.videoTargeting().excludedYouTubeChannels().get();
    while (exludedYoutubeChannelIterator.hasNext()) {
      var excludedYouTubeChannel = exludedYoutubeChannelIterator.next();
      alreadyExcludedYouTubeChannels.push(excludedYouTubeChannel.getChannelId());
    }
    // Build a batch with to be excluded YouTube channels
    const toBeExcludedYouTubeChannels = checkYouTubeChannels(videoCampaign.getId(),alreadyExcludedYouTubeChannels);
    // Exclude all YouTube channels in batch from campaign
    for (i=0;i&lt;toBeExcludedYouTubeChannels.length;i++){
      videoCampaign.videoTargeting().newYouTubeChannelBuilder().withChannelId(toBeExcludedYouTubeChannels&#91;i].id).exclude();
    }
    // Add logging information to log array
    allExclusions.push({ campaign: videoCampaign.getName(), excludedYouTubeChannels: toBeExcludedYouTubeChannels })
  }
  // Prepare and send a notification email with logging information
  sendConfirmationEmail(allExclusions);
}

function checkYouTubeChannels(campaignId,alreadyExcludedYouTubeChannels){
  // Prepare an array for the return values  
  var toBeExcludedYouTubeChannels = &#91;];
  // Load currently known allowed YouTube Channels from Google Sheet
  var knownAllowedYouTubeChannels = getAllowedYouTubeChannels();
  // Prepare an array for newly identified allowed YouTube Channels to be added to the Google Sheet
  var newAllowedYouTubeChannels = &#91;];
  // Query all YouTube placements of the processed campaign with at least ${impressionsThreshold} impressions within the ${impressionsTimeRange}
  var query = 
    "SELECT detail_placement_view.display_name, detail_placement_view.group_placement_target_url FROM detail_placement_view " +
    "WHERE " +
    "  campaign.id = " + campaignId +
    "  AND segments.date DURING " + impressionsTimeRange +
    "  AND metrics.impressions &gt; " + impressionsThreshold + 
    "  AND detail_placement_view.placement_type IN ('YOUTUBE_VIDEO','YOUTUBE_CHANNEL') " +
    "  AND detail_placement_view.group_placement_target_url IS NOT NULL " +
    "  AND detail_placement_view.group_placement_target_url NOT REGEXP_MATCH '" + alreadyExcludedYouTubeChannels.join("|") + "'" +
    "  AND detail_placement_view.group_placement_target_url NOT REGEXP_MATCH '" + knownAllowedYouTubeChannels.join("|") + "'" +
    ""
    ;
  var result = AdsApp.search(query);
  console.log(result.totalNumEntities() + " YouTube Placements found.");
  while (result.hasNext()) {
    var row = result.next();
    const channelId = row&#91;'detailPlacementView']&#91;'groupPlacementTargetUrl'].match(/^.*\/(&#91;^\/]*)$/)&#91;1];
    const channelName = row&#91;'detailPlacementView']&#91;'displayName'];
    const channelInfo = getChannelInfo(channelId); // &#91; Country, Default Language ]
    if ( channelInfo &amp;&amp; channelInfo&#91;0]){
      if (channelInfo&#91;0].match(allowedCountries) &amp;&amp; knownAllowedYouTubeChannels.indexOf(channelId) == -1 &amp;&amp; newAllowedYouTubeChannels.indexOf(channelId) == -1){
        // Store channel id of newly identified German YouTube Channel in array to be added to Google Sheet
        newAllowedYouTubeChannels.push(channelId);
      }
      else if (!channelInfo&#91;0].match(allowedCountries)){
        if ( alreadyExcludedYouTubeChannels.indexOf(channelId) == -1){
          toBeExcludedYouTubeChannels.push(
            {
              id: channelId,
              name: channelName,
              country: channelInfo&#91;0],
              language: channelInfo&#91;1]
            }
          );
        }
      }
    }
  }
  if (newAllowedYouTubeChannels.length &gt; 0){
    saveAllowedYouTubeChannels(newAllowedYouTubeChannels);
    newAllowedYouTubeChannels.length.toLocaleString("de") + " new allowed Channel(s) found." + "\n\n";
  }
  return toBeExcludedYouTubeChannels.sort();
}

function getChannelInfo(channelId){
  try {
    const results = YouTube.Channels.list('snippet,localizations', {
      id: channelId,
      maxResults: 1
    });
    if (results === null) {
      console.log(`ID ${channelId}: Unable to search videos`);
      return;
    }
    return &#91; results.items&#91;0].snippet.country, results.items&#91;0].snippet.defaultLanguage ];
  } catch (err) {
    // TODO (developer) - Handle exceptions from Youtube API
    console.log(`ID ${channelId}: Failed with an error: %s`, err.message);
  }  
}

function getAllowedYouTubeChannels(){
  var sheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL).getSheetByName(SHEET_NAME);
  var lastRow = sheet.getLastRow();
  var range = sheet.getRange(1, 1, lastRow);
  var returnValues = &#91;];
  var values = range.getValues();
  for (var row in values) {
    for (var col in values&#91;row]) {
      returnValues.push(values&#91;row]&#91;col]);
    }
  }
  return returnValues;
}

function saveAllowedYouTubeChannels(newAllowedYouTubeChannels){
  var sheet = SpreadsheetApp.openByUrl(SPREADSHEET_URL).getSheetByName(SHEET_NAME);
  var lastRow = sheet.getLastRow();
  var range = sheet.getRange(lastRow+1,1,newAllowedYouTubeChannels.length);
  var outputValues = &#91;];
  while(newAllowedYouTubeChannels.length) outputValues.push(newAllowedYouTubeChannels.splice(0,1));
  range.setValues(outputValues);
  sheet.sort(1);
}

function sendConfirmationEmail(allExclusions){
  var output = "";
  for (i=0;i&lt;allExclusions.length;i++){
    output += allExclusions&#91;i].excludedYouTubeChannels.length.toLocaleString("de") + " Channel(s) excluded from Campaign " + allExclusions&#91;i].campaign + "\n\n";
    var outputChannels = "";
    for (j=0;j&lt;allExclusions&#91;i].excludedYouTubeChannels.length;j++){
        outputChannels += allExclusions&#91;i].excludedYouTubeChannels&#91;j].name + " (" + allExclusions&#91;i].excludedYouTubeChannels&#91;j].country + "|" + allExclusions&#91;i].excludedYouTubeChannels&#91;j].language + ")\n";
        outputChannels += "https://youtube.com/channel/" + allExclusions&#91;i].excludedYouTubeChannels&#91;j].id + "\n\n";
    }
    output += outputChannels;
  }  
  var eMailAddress = EMAIL_ADRESSES;
  var eMailSubject = "YouTube Channel Excluder";
  var eMailContent = output;
  console.log(output);
  sendSimpleTextEmail(eMailAddress,eMailSubject,eMailContent)
}

// HELPERS

function sendSimpleTextEmail(eMailAddress,eMailSubject,eMailContent) {
  MailApp.sendEmail(eMailAddress,eMailSubject,eMailContent);
  Logger.log("Mail sent.");
}</code></pre>
<p>The post <a href="https://www.adtraffic.de/google-ads-script-youtube-channel-excluder/">Google Ads Script: YouTube Channel Excluder</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Google Looker Studio Reports: Ladezeiten deutlich verkürzen</title>
		<link>https://www.adtraffic.de/google-looker-studio-reports-ladezeiten-deutlich-verkurzen/</link>
		
		<dc:creator><![CDATA[pp_admin]]></dc:creator>
		<pubDate>Fri, 22 Jul 2022 12:27:53 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<guid isPermaLink="false">https://www.adtraffic.de/?p=100</guid>

					<description><![CDATA[<p>Sekundenschnelle Berichte trotz Millionen von Daten aus einer Vielzahl unterschiedlicher Kanäle. Wir erklären, wie es geht. Mit zunehmender Komplexität geht Google Looker Studio in die Knie und bedankt sich mit sehr langen Ladezeiten. Ein Multichannel Reporting umfasst bei uns schnell mal 110 Diagramme und 48 Filter auf 13 Seiten. Im nachfolgenden Artikel wird erklärt, wie [&#8230;]</p>
<p>The post <a href="https://www.adtraffic.de/google-looker-studio-reports-ladezeiten-deutlich-verkurzen/">Google Looker Studio Reports: Ladezeiten deutlich verkürzen</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><strong>Sekundenschnelle Berichte trotz Millionen von Daten aus einer Vielzahl unterschiedlicher Kanäle. Wir erklären, wie es geht.</strong></p>



<p>Mit zunehmender Komplexität geht Google Looker Studio in die Knie und bedankt sich mit sehr langen Ladezeiten. Ein Multichannel Reporting umfasst bei uns schnell mal 110 Diagramme und 48 Filter auf 13 Seiten.</p>



<p>Im nachfolgenden Artikel wird erklärt, wie man durch die Aufbereitung der Daten in BigQuery die Geschwindigkeit und damit die Bedienungsfreundlichkeit von Looker Studio Reports erheblich steigern kann.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>— innerhalb weniger Sekunden —</em></p>
</blockquote>



<p>Denn die lange Ladezeit liegt an der Aggregation und Verarbeitung der Daten von Google Looker Studio. Wenn die Daten vorher in BigQuery aufbereitet werden, laden auch Looker Studio Reports mit mehreren hunderttausend Produkten und Millionen Datenpunkten innerhalb weniger Sekunden.</p>



<h2 class="wp-block-heading">Wie sieht eine optimierte Datenquelle für Looker Studio aus?</h2>



<p>Ziel ist es, eine einzige, möglichst flache Datenquelle zu generieren. Aus dieser kann Looker Studio die Daten für die Diagramme und Filter ziehen, ohne diese vorher mit weiteren Datenquellen verknüpfen zu müssen oder komplizierte Berechnungen in benutzerdefinierten Feldern innerhalb der Datenquelle durchführen zu müssen. Stellen Sie deshalb zunächst zusammen, welche Messwerte dargestellt werden sollen und nach welchen Dimensionen Sie diese filtern oder segmentieren möchten.</p>



<p>Für unser Beispiel benötigen wir folgende Datenfelder:</p>



<ul class="wp-block-list">
<li>Messwerte: Besuche, Bestellungen, Neukunden, Umsatz, Kosten</li>



<li>Berechnete Felder: Konversionsrate, Kosten/Umsatz-Relation, Neukundenquote</li>



<li>Dimensionen: Datum, Kanal, Unterkanal</li>
</ul>



<p>Um später bei der Wahl der Auswertungszeiträume und etwaiger Vergleichszeiträume, sowie bei der segmentierten Darstellung – zum Beispiel nach Wochen – möglichst flexibel zu sein, benötigen Sie die Daten auf Tagesbasis.</p>



<p>So könnte die Kopfzeile der benötigten Datenquelle aussehen:</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.adtraffic.de/wp-content/uploads/Bildschirmfoto-2022-07-22-um-10.24.39.png" alt="" class="wp-image-4869"/></figure>



<h2 class="wp-block-heading">Woher kommen die Daten für das Reporting?</h2>



<p>Besuche, Bestellungen, Neukunden und Umsatz je Datum, Kanal und Unterkanal erhalten Sie idealerweise aus Ihrem Webanalysetool. Mit Tools wie Supermetrics lassen sich die Daten automatisiert abrufen und zum Beispiel in einem Google Sheet oder direkt in BigQuery speichern.</p>



<p>Die Kostendaten stammen üblicherweise direkt von den Plattformen, in unserem Beispiel aggregieren wir diese von Google, Bing, Meta und drei Preisvergleichsportalen. Auch die Daten der ersten drei Anbieter können Sie über Tools sehr einfach in der benötigten Form abrufen. Bei den Preisvergleichern müssen Sie aber vermutlich improvisieren:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>— Automatisieren mit Scripts —</em></p>
</blockquote>



<p>Nehmen wir an, der erste Preisvergleicher schickt die Daten als Anlage per E-Mail, der zweite lädt sie via FTP auf Ihren Server hoch und der dritte bietet einen Datenabruf mittels API an. Spätestens an dieser Stelle würden einige vermutlich zur manuellen Übertragung wechseln und die relevanten Daten aus den Reports der Preisvergleicher in ein Google Sheet importieren. Wir automatisieren das in unserem Beispiel mit einem kleinen Bash Script und zwei kleinen Google Scripts.</p>



<h2 class="wp-block-heading">Wie kommen die Daten in Form?</h2>



<p>Die zusammengestellten Kostendaten müssen später anhand von Datum, Kanal und Unterkanal der jeweiligen Datenzeile aus dem Webanalysetool zugeordnet werden. Dabei hilft eine schematische Benennung aller Kampagnen und/oder ein durchgängiges Tracking mit URL-Parametern.</p>



<p>In unserem Beispiel verwenden wir vom Kunden definierte Kampagnen-Codes, die in allen Kampagnen als URL-Parameter angehängt werden. Mithilfe der Kampagnen-Codes und einer Matching-Tabelle können wir sowohl Kostendaten als auch die Daten aus der Webanalyse eindeutig einem Unterkanal zuordnen.</p>



<p>Als Zwischenstufe können Sie sich folgende Rohdatenquellen vorstellen:</p>



<p>Daten aus der Webanalyse:</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.adtraffic.de/wp-content/uploads/Bildschirmfoto-2022-07-22-um-10.25.37.png" alt="" class="wp-image-4870"/></figure>



<p>Kostendaten je Plattform:</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.adtraffic.de/wp-content/uploads/Bildschirmfoto-2022-07-22-um-10.27.22.png" alt="" class="wp-image-4871"/></figure>



<p>Matching-Tabelle für Kampagnen-Codes:</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.adtraffic.de/wp-content/uploads/Bildschirmfoto-2022-07-22-um-10.27.52.png" alt="" class="wp-image-4872"/></figure>



<p>Liegen alle Daten in dieser Form vor, ist es mit BigQuery relativ einfach, diese zu einer flachen Datenquelle für Looker Studio zu kombinieren. Aber eins nach dem anderen…</p>



<h2 class="wp-block-heading">Vorbereitung (optional)</h2>



<p>Für die weiteren Schritte ist es hilfreich, wenn Sie sich bereits mit Ihrem Google Konto in der Google Cloud angemeldet und dort in BigQuery ein Projekt mit einem Dataset eingerichtet haben.&nbsp;</p>



<p>Einen Einstieg in die Funktionsweise von Abfragen in BigQuery erhalten Sie hier:&nbsp;<a href="https://cloud.google.com/bigquery/docs/query-overview">Overview of BigQuery analytics | Google Cloud</a>. Wenn Sie noch eine Stufe früher einsteigen möchten, beginnen Sie am Besten hier:&nbsp;<a href="https://cloud.google.com/bigquery/docs/sandbox">Enable the BigQuery sandbox | Google Cloud</a>.</p>



<h2 class="wp-block-heading">Abrufen und Importieren der Daten in BigQuery</h2>



<p>Wir nutzen in unserem Beispiel das Tool Supermetrics for Google Sheets und speichern die abgerufenen Daten in einem Google Sheet, das wir anschließend als externe Tabelle in BigQuery importieren. Dazu erstellen wir in unserem Dataset eine neue Tabelle aus “Drive” im Dateiformat “Google-Tabelle” unter Angabe der URL des Google Sheets.</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.adtraffic.de/wp-content/uploads/Bildschirmfoto-2022-07-22-um-10.28.48.png" alt="" class="wp-image-4873"/></figure>



<p>Als Ziel des Imports definieren wir in unserem bestehenden Dataset eine neue Tabelle, der wir einen sprechenden Namen geben, zum Beispiel “import_webanalyse”:</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.adtraffic.de/wp-content/uploads/Bildschirmfoto-2022-07-22-um-10.29.15.png" alt="" class="wp-image-4874"/></figure>



<p>Das Schema für die Tabelle, also die Feldnamen und jeweiligen Datentypen, definieren wir manuell mit sprechenden Bezeichnungen für die weitere Verwendung in SQL-Abfragen:</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.adtraffic.de/wp-content/uploads/Bildschirmfoto-2022-07-22-um-10.29.41.png" alt="" class="wp-image-4875"/></figure>



<p>Sofern im Google Sheet eine Kopfzeile vorhanden ist, überspringen wir diese beim Import:</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.adtraffic.de/wp-content/uploads/Bildschirmfoto-2022-07-22-um-10.30.05.png" alt="" class="wp-image-4876"/></figure>



<p>Mit Klick auf “Tabelle erstellen” ist das Google Sheet den Quelldaten mit BigQuery verknüpft. Diesen Vorgang wiederholen wir für alle zu importierenden Google Sheets.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>— Sheets als temporäre Datenpools nutzen —</em></p>
</blockquote>



<p>Werden Daten dieser Tabellen abgefragt, lädt BigQuery diese Daten aus dem jeweiligen Google Sheet, was bei großen Datenmengen zu Verzögerungen führen kann. Die Google Sheets können aber auch als temporäre Datenpools genutzt werden. Mittels regelmäßiger Abfragen können die jeweils neuen Daten aus den Google Sheets in eine eigens dafür erstellte, interne BigQuery Tabelle übertragen respektive angehängt werden.</p>



<p>Diese Methode funktioniert hervorragend für Daten, die automatisiert mit Tools abgerufen werden können oder in standardisierten Formaten vorliegen. Unsere Lösung für Sonderfälle haben wir am Beispiel der drei Preisvergleichsportale am Ende des Artikels angehängt.</p>



<h2 class="wp-block-heading">Erstellung der Datenquelle für Looker Studio</h2>



<p>Mit SQL können wir die vollständig importierten Daten nicht nur einfach zusammenfügen, sondern gegebenenfalls auch Berechnungen&nbsp;<em>mit</em>&nbsp;oder Modifikationen&nbsp;<em>an</em>&nbsp;den Daten vornehmen. Eine SQL-Abfrage zur Zusammenführung der Daten aus sechs Datenquellen und einer Matching-Tabelle kann sauber formatiert schon mal über 100 Zeilen lang sein.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><em>— Werte vorab modellieren —</em></p>
</blockquote>



<p>Wir verwenden für Abfragen uneinheitlicher Kostendaten WITH Statements, um Feldnamen aber auch manche Werte vorab zu modellieren, damit sie im nächsten Schritt über UNION ALL zu einer homogenen Datenquelle zusammengefasst und anschließend mit LEFT JOIN sauber zugeordnet werden können. Das ist insbesondere dann sehr hilfreich, wenn eine wichtige ID, wie in unserem Beispiel der Kampagnen-Code, nicht als separates Feld in der Datenquelle zur Verfügung steht, sondern aus einem anderen Textfeld&nbsp;<em>extrahiert</em>&nbsp;werden muss.</p>



<p>Das Ergebnis unserer Abfrage schreiben wir in eine neue Tabelle die wir später in Looker Studio als Quelle hinzufügen können. Die Option finden Sie im BigQuery Abfrageeditor unter “MEHR &gt; Abfrageeinstellungen”:</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.adtraffic.de/wp-content/uploads/Bildschirmfoto-2022-07-22-um-10.31.20.png" alt="" class="wp-image-4877"/></figure>



<p>Die Datenquelle für Looker Studio können Sie aktuell halten, indem Sie eine leicht modifizierte Abfrage als geplanten Abfrage speichern, die täglich automatisiert die neuen Daten anhängt.</p>



<h2 class="wp-block-heading">Hinzufügen der Datenquelle zu Looker Studio</h2>



<p>Die fertig vorbereitete Datenquelle verknüpfen Sie aus Looker Studio heraus ganz einfach, indem Sie unter “Daten hinzufügen” den Connector für BigQuery anklicken und anschließend aus Ihrem Projekt und Dataset die neu erstellte Exporttabelle auswählen.</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.adtraffic.de/wp-content/uploads/Bildschirmfoto-2022-07-22-um-10.31.58.png" alt="" class="wp-image-4879"/></figure>



<p>Ab hier können Sie nun wie gewohnt mit der Zusammenstellung Ihres Reports in Looker Studio loslegen. Mit dem großen Unterschied, dass Sie keine Tabellen mehr verknüpfen müssen und die einzelnen Seiten deutlich schneller geladen werden.</p>



<p>In unserem Beispiel haben wir drei berechnete Felder vorgesehen. Diese können Sie natürlich bereits in der SQL-Abfrage zur Erstellung der Exporttabelle ergänzen. Es ist aber auch möglich, innerhalb von Looker Studio einer BigQuery Datenquelle berechnete Felder hinzuzufügen.</p>



<p>Viel Spaß und Erfolg beim Reporting Ihrer Kampagnen-Performance!</p>



<h2 class="wp-block-heading">Darauf können Sie zählen</h2>



<p>Wieviel die Optimierung von Datenquellen mit BigQuery für Looker Studio bringt, zeigt sich vor allem bei umfangreichen Reports.</p>



<p>Unser jüngstes Projekt besteht zum Beispiel aus:</p>



<ul class="wp-block-list">
<li>123 Diagrammen</li>



<li>auf 16 Seiten</li>



<li>aus vier optimierten Datenquellen</li>



<li>davon 12 Diagramme aus zwei separaten Datenquellen</li>



<li>und eine zusätzliche Import-Statustabelle mit separater Datenquelle</li>
</ul>



<p>110 Diagramme und 48 Filter auf 13 Seiten entspringen also nur einer einzelnen Datenquelle.</p>



<p>Im gesamten Reporting werden nur sechs berechnete Felder verwendet. Es wird keine einzige zusammengefügte Datenquelle benötigt.</p>



<p>Die Seiten dieses Reporting laden spürbar schneller als ein vergleichbares Reporting mit direkter Google Analytics und Google Ads Verknüpfung und sogar deutlich schneller als ein weiteres Kundenreporting mit einer Vielzahl direkter Google Analytics Verknüpfungen.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p></p>



<h2 class="wp-block-heading">ANHANG</h2>



<h2 class="wp-block-heading">Sonderfälle auf Spur bringen</h2>



<p>Manche Daten können nicht standardisiert über Tools abgerufen werden. In dem Fall gilt es, zwei Herausforderungen zu meistern: Zuerst sollen die Daten automatisiert empfangen und eingelesen werden. Anschließend sollen sie verarbeitet und in Form für den weiteren Import in BigQuery gebracht werden. Dabei kann erschwerend hinzukommen, dass die Daten mehrerer gleich zu behandelnder Quellen völlig unterschiedlich ankommen.</p>



<p>Um ein Beispiel zu nennen: Ein Preisvergleicher schickt per E-Mail die Kostendaten pro Tag inklusive der Anzahl an Impressionen und Klicks. Der zweite lädt eine Datei mit einer Zeile pro Klick via FTP auf unseren Server – ohne Kostendaten. Und der dritte stellt eine REST-API zur Verfügung, über die tagesgenau sowohl Kosten als auch Klicks abgefragt werden können, nicht aber die Impressionen.</p>



<p>Am Ende soll ein Google Sheet herauskommen, das folgende Kopfzeile haben könnte:</p>



<figure class="wp-block-image"><img decoding="async" src="https://www.adtraffic.de/wp-content/uploads/Bildschirmfoto-2022-07-22-um-10.33.34.png" alt="" class="wp-image-4880"/></figure>



<p>Um die Daten in dieser Form aufzubereiten und an das Sheet anzuhängen, nutzen wir Google Apps Scripts in zwei Ausführungen: Eine Variante liest die Daten aus den Anhängen der E-Mails, die über ein dediziertes Reporting-Postfach empfangen wurden. Die andere ruft die Daten über REST-APIs ab. Beiden folgt eine einheitliche Export-Funktion zur Übertragung der aufbereiteten Daten in das gemeinsame Google Sheet.</p>



<p>Das funktioniert deshalb so reibungslos, weil Google Apps Scripts sehr unkompliziert mit GMail und Google Sheets interagieren kann. Die via FTP empfangenen Daten senden wir deshalb mittels Bash-Script direkt vom FTP-Server ebenfalls an das Reporting-Postfach und führen sie so der automatisierten Weiterverarbeitung zu.</p>



<p>So kann das ordentlich formatierte Google Sheet auch einfach in BigQuery importiert werden (siehe Abrufen und Importieren der Daten in BigQuery).</p>



<p>Nachfolgend finden Sie einige Beispielcodes dazu.</p>



<h2 class="wp-block-heading">In Google Sheet schreiben</h2>



<p>Fertig aggregierte Daten lassen sich mittels Google Apps Script ganz einfach in ein Google Sheet schreiben.</p>



<pre class="wp-block-code"><code>function writeData(fileID,sheetName,output){
  if (output.length === 0) { return; }
  var sheet = SpreadsheetApp.openById(fileID).getSheetByName(sheetName);
  var lastRow = sheet.getLastRow();
  var lastColumn = sheet.getLastColumn();
  sheet.getRange(lastRow + 1, 1, output.length, lastColumn).setValues(output);
}</code></pre>



<h2 class="wp-block-heading">E-Mail-Anhänge auslesen</h2>



<p>Die zu aggregierenden CSV-Daten lassen sich aus E-Mail-Anhängen ebenfalls sehr einfach mit Google Apps Script auslesen.</p>



<pre class="wp-block-code"><code>function iterateThreads(query){
  var threads = GmailApp.search(query,0,3);
  for(i=0;i&lt;threads.length;i++){
    var subject = threads&#91;i].getFirstMessageSubject();
    var messages = threads&#91;i].getMessages();
    var message = messages&#91;messages.length-1];
    var date = message.getDate();
    var attachment = message.getAttachments({includeInlineImages:false})&#91;0];
    processAttachement(date,attachment); // verarbeitet den E-Mail-Anhang
    GmailApp.moveThreadToArchive(threads&#91;i]);
  }
}

function processAttachement(date,attachment){
  var separator = ";"
  var csvData = Utilities.parseCsv(attachment.getDataAsString(), separator);
  var impressions = 0;
  var clicks = 0;
  var cost = 0;
  for (i=1;i&lt;csvData.length-1;i++){
    var line = csvData&#91;i]&#91;0].split(",");
    if (parseInt(line&#91;2]) &amp;&amp; parseInt(line&#91;3]) &amp;&amp; parseFloat(line&#91;4])){
      impressions += parseInt(line&#91;2]);
      clicks += parseInt(line&#91;3]);
      cost += parseFloat(line&#91;4]);
    }
  }
  prepareData(date,impressions,clicks,cost);
}</code></pre>



<h2 class="wp-block-heading">Daten abgleichen und in Form bringen</h2>



<p>Die ausgelesenen Daten lassen sich anschließend mit ein paar Codezeilen mit den bereits bestehenden Daten abgleichen und vor dem Schreiben in das Google Sheet in Form bringen.</p>



<pre class="wp-block-code"><code>function prepareData(date,impressions,clicks,cost){
  if (checkIfExisting(date) === 0){
    output.push(&#91;date,impressions,clicks,cost]); // schreibt in globale Variable
  }
}

function checkIfExisting(date){
  var values = readSheetValues(fileID,sheetName);
  if (!values) { return 0; }
  var filtered = values.filter(function(e){
    if (e.indexOf(date) != -1){
      return 1;
    }
  });
  return filtered.length;
}

function readSheetValues(fileID,sheetName){
  sheet = SpreadsheetApp.openById(fileID).getSheetByName(sheetName);
  lastRow = sheet.getLastRow();
  lastColumn = sheet.getLastColumn();
  if (lastRow === 1) {
    return;
  }
  return sheet.getRange(2,1,lastRow-1,lastColumn).getValues();
}</code></pre>



<h2 class="wp-block-heading">Unterschiedlich formatierte Daten</h2>



<p>Bei unterschiedlichen Formatierungen der eingehenden CSV-Daten kann man sich mit Prozessschleifen behelfen.</p>



<pre class="wp-block-code"><code>else if (comp === "ladenzeile") {
    var date = fileName.match(/(\d{4}-\d{2}-\d{2})/)&#91;1];
    var clicks = 0;
    var cost = 0;
    for (i=1;i&lt;csvData.length-1;i++){
      var line = csvData&#91;i];
      clicks += 1;
      cost += parseFloat(line&#91;5]);
    }
    prepareData(date,comp,0,clicks,cost);
  }</code></pre>



<h2 class="wp-block-heading">Abruf über APIs</h2>



<p>Auch über REST-APIs lassen sich mittels Google Apps Script relativ einfach Daten abrufen.</p>



<pre class="wp-block-code"><code>function idealoMain(){
  Logger.log("Processing idealo");
  const sysdate = new Date();
  const offset = new Date().getTimezoneOffset();
  const today = new Date(sysdate.getTime() - (offset*60*1000));
  today.setDate( today.getDate() - 1 );
  const querydate = today.toISOString().split("T")&#91;0];
  const shopId = "123456789";
  const siteId = "IDEALO_DE";
  const fromDate = querydate;
  const toDate = querydate;
  const cpc = 0.12;
  const access_token = idealoGetAccessToken();
  const idealoClickReport = idealoDownloadDailyClickReport(shopId,siteId,fromDate,toDate,access_token);
  var dataLength = idealoClickReport.findIndex(function(el){ return el&#91;0] === ""});
  for(i=1;i&lt;dataLength;i++){
    var line = idealoClickReport&#91;i]&#91;1].split(';')
    var date = line&#91;0].match(/(\d{4}-\d{2}-\d{2})/)&#91;1]
    var clicks = line&#91;1];
    var cost = line&#91;1] * cpc;
    prepareData(date,"idealo",0,clicks,cost)
  }
}

function idealoGetAccessToken(){
	const url = "https://businessapi.idealo.com/api/v1/oauth/token";
	const response = UrlFetchApp.fetch(url, {
		"method": "POST",
		"headers": {
			"Authorization": "Basic ************************************************",
			"Content-Type": "application/javascript",
		},
		"muteHttpExceptions": true,
		"followRedirects": true,
		"validateHttpsCertificates": true,
		"contentType": "application/javascript",
		});
  return JSON.parse(response.getContentText()).access_token;
}





function idealoDownloadDailyClickReport(shopId,siteId,fromDate,toDate,access_token){
	const url = "https://businessapi.idealo.com/api/v1/shops/"+shopId+"/daily-click-reports/download?site="+siteId+"&amp;from="+fromDate+"&amp;to="+toDate;
	const response = UrlFetchApp.fetch(url, {
		"method": "GET",
		"headers": {
			"Authorization": "Bearer "+access_token,
			"Content-Type": "application/json",
		},
		"muteHttpExceptions": true,
		"followRedirects": true,
		"validateHttpsCertificates": true,
		"contentType": "application/json",
		});
  return Utilities.parseCsv(response);
}</code></pre>



<h2 class="wp-block-heading">Workaround für FTP-Empfang</h2>



<p>Um via FTP empfangene CSV-Daten auf die gleiche Weise verarbeiten zu können, schicken wir sie uns mittels BASH-Script als Anhang per E-Mail an unser Reporting-Postfach.</p>



<pre class="wp-block-code"><code><strong>#!/bin/bash</strong>
inotifywait -m -r /var/www/********/htdocs/******** -e create -e moved_to |
    while read dir action file; do
 	sleep 10
	subdir="main"
	needle="\/(.&#91;^\/]*)\/$"
	if &#91;&#91; $dir =~ $needle ]]
	then
	subdir="${BASH_REMATCH&#91;1]}"
	fi
        echo "The file '$file' appeared in sub-directory '$subdir' via '$action'"
        echo "Datei '$file' von '$subdir' via FTP empfangen ." | mutt -x -s "******** $subdir reportings" -a $dir$file -- ********@adtraffic.de
	today=$(date +"%Y%m%d")
	mkdir /var/www/********/htdocs/********/$subdir
	mkdir /var/www/********/htdocs/********/$subdir/$today
	mv -f $dir$file /var/www/********/htdocs/********/$subdir/$today/$file</code></pre>
<p>The post <a href="https://www.adtraffic.de/google-looker-studio-reports-ladezeiten-deutlich-verkurzen/">Google Looker Studio Reports: Ladezeiten deutlich verkürzen</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>In Data We Trust? – können wir den Daten der Online Marketing Plattformen vertrauen?</title>
		<link>https://www.adtraffic.de/in-data-we-trust-koennen-wir-den-daten-der-online-marketing-plattformen-vertrauen/</link>
		
		<dc:creator><![CDATA[pp_admin]]></dc:creator>
		<pubDate>Sat, 30 Apr 2022 12:27:43 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<guid isPermaLink="false">https://www.adtraffic.de/?p=98</guid>

					<description><![CDATA[<p>Ein Kommentar von Lukas Meyer, Director Consulting &#38; Operations bei der adtraffic GmbH Berlin, im April 2022.&#160;Daten sind das neue Gold! Daten sind das neue Öl! Daten sind das neue Wasser! Diese Vergleiche sind hinlänglich bekannt und verdeutlichen: Daten sind sehr wertvoll. Aber welchen Daten können wir vertrauen? Am besten schenkt man nur Daten&#160;Vertrauen, die [&#8230;]</p>
<p>The post <a href="https://www.adtraffic.de/in-data-we-trust-koennen-wir-den-daten-der-online-marketing-plattformen-vertrauen/">In Data We Trust? – können wir den Daten der Online Marketing Plattformen vertrauen?</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p><em>Ein Kommentar von Lukas Meyer, Director Consulting &amp; Operations bei der adtraffic GmbH</em></p>



<p><em>Berlin, im April 2022.&nbsp;</em>Daten sind das neue Gold! Daten sind das neue Öl! Daten sind das neue Wasser! Diese Vergleiche sind hinlänglich bekannt und verdeutlichen: Daten sind sehr wertvoll. Aber welchen Daten können wir vertrauen? Am besten schenkt man nur Daten&nbsp;<strong>Vertrauen</strong>, die man selbst erhoben hat oder bei denen man in der Lage ist, sie zu prüfen. Im Folgenden veranschauliche ich anhand von Meta (Facebook &amp; Instagram) und Google Ads, wieso&nbsp;<strong>Skepsis</strong>&nbsp;gegenüber den erhobenen Daten angebracht ist.</p>



<h3 class="wp-block-heading"><strong>Wie Agenturen und Plattformen täuschen</strong></h3>



<p>Im (Online) Marketing gibt es viele sogenannte&nbsp;<strong>Vanity Metrics</strong>. Also Zahlen, die vermeintlichen Erfolg suggerieren, aber letztlich wenig Aussagekraft haben. Weit vorne dabei sind auch die KPIs der Plattform Meta (Facebook &amp; Instagram). Im Business Manager von Meta kann man&nbsp;<strong>über 100 unterschiedliche KPIs</strong>&nbsp;auswerten. Diese KPIs werden oft fehlinterpretiert oder bewusst falsch ausgelegt.</p>



<p>Die meisten&nbsp;<strong>Kennzahlen</strong>&nbsp;davon sind so aussagekräftig, wie wenn H&amp;M messen würde, wie viele Personen ein Kleidungsstück angesehen, angefasst und anprobiert haben und davon das Verhältnis ausrechnen. Bitte nicht falsch verstehen – das wäre sicherlich interessant und man kann anhand der Daten vieles interpretieren und manches im Prozess verbessern. Wenn alle im Geschäft das Produkt nur anfassen und niemand probiert es an, dann hat das Kleidungsstück wohl ein unangenehmes Material.&nbsp;</p>



<p>Man darf sich von den&nbsp;<strong>„soften“ Kennzahlen</strong>, die oft sehr hoch ausfallen, nicht blenden lassen und muss wissen, wie diese zu verstehen sind. Meta trackt Interaktionen und man kann diese für die Auswertung einer Anzeige heranziehen. Man sollte aber dabei im Hinterkopf behalten, dass die Hälfte der Interaktionen von eigenen Mitarbeitern oder Nutzern stammt, die einfach alles liken. Übrigens: Interaktionen sind nicht nur Likes oder Kommentare, auch ein Fotoaufruf oder 3-sekündige Videowiedergaben werden als Interaktion gemessen. Die Definition der jeweiligen Kennzahl erfährt man mit einem „Maus-hoovern“ über die Bezeichnung.</p>



<p>Wirklich wichtig sind den meisten Unternehmen&nbsp;<strong>„harte Zahlen“</strong>&nbsp;wie Käufe, Umsatz oder qualifizierte Leads und vielleicht noch die erzielten Besucher der Webseite.</p>



<h3 class="wp-block-heading"><strong>Warum trackt Meta so viele Käufe?</strong></h3>



<p>Viele kennen das: im Business Manager wird im Vergleich zum eigenen CRM oder Google Analytics ein Vielfaches an Käufen ausgewiesen. Die Ursachen dafür sind vielfältig, mit den richtigen Einstellungen kann man sich jedoch den tatsächlichen Zahlen annähern. Wenn kein Fehler beim Pixel oder Tracking vorliegt, hängt das maßgeblich mit den&nbsp;<strong>Attributionseinstellungen</strong>&nbsp;zusammen. Dort legt man fest, wann ein Kauf der Facebook-Anzeige zugerechnet wird. Man wählt den Zeitraum, 1 oder 7 Tage und ob der Kauf nur bei Ansehen der Anzeige oder bei Klick der Anzeige zugerechnet werden soll. Hinzu kommt, dass die Kennzahlen&nbsp;<strong>Schätzwerte</strong>&nbsp;sind.</p>



<p>Ein schönerer Ausdruck dafür ist&nbsp;<strong>Modellieren</strong>. Spätestens seit Corona ist das jedem ein Begriff. Modellieren ist sowohl bei Corona als auch bei Meta selbstverständlich sehr hilfreich. Denn man kann damit Tendenzen erkennen, bewerten und schlussfolgern. Wichtig ist, nicht zu vergessen, dass Schätzwerte und Modellierungen&nbsp;<strong>nie die Wahrheit</strong>&nbsp;sind und deshalb auch nicht als solche verstanden werden sollten.</p>



<p>Dass im Onlinemarketing heute so viel modelliert wird, haben wir nicht Corona, sondern den verschärften DSGVO-Richtlinien und dem IOS14-Update zu verdanken. Seitdem können deutlich weniger&nbsp;<strong>„echte“ Daten</strong>&nbsp;getrackt werden.</p>



<h3 class="wp-block-heading"><strong>Wie kommen die Schätzwerte bei Meta zustande?</strong></h3>



<p>Wie die Schätzwerte zustande kommen, ist nicht genau bekannt, denn dahinter verbergen sich&nbsp;<strong>komplexe Algorithmen</strong>, die laut Aussagen von hochrangigen Meta-Mitarbeitern heute niemand mehr versteht. Man kann annehmen, dass Meta bei den Schätzwerten ähnlich konservativ vorgeht, wie man es von den Automobilherstellern oder anderen Werbeversprechen kennt: den Verbrauch von 4,8L auf 100 km kann man nicht einmal auf einer optimalen Teststrecke erreichen. Tatsächlich sind es bei 80 auf der Landstraße dann im besten Fall 6,4L auf 100 km.</p>



<p><em>Tipp:</em></p>



<p><em>Vertrauen Sie nicht blind den Plattform-Daten, sondern überprüfen Sie diese immer mit einem oder mehreren&nbsp;</em><strong><em>Drittanbieter Tools</em></strong><em>, wie bspw. Google Analytics. Die Wahrheit in den Daten zu finden, ist unmöglich. Mit dem richtigen Tracking, Attributionseinstellungen, Datenabgleichen und Reportings kann man sich dieser annähern. Vergessen Sie bei den vielen Plattform-Daten nicht die eigenen Website-Daten (</em><strong><em>First Party Daten</em></strong><em>) zu nutzen und auszuwerten, denn diese tragen meist mehr zum wirtschaftlichen Erfolg bei.</em></p>



<p>Auch die Metriken bei Google Ads sollte man kritisch hinterfragen. Überraschend dabei ist die KPI&nbsp;<strong>„sichtbare Impressionen“</strong>&nbsp;bei Display Anzeigen. Das bedeutet: unter den „Impressionen“ befinden sich auch Anzeigenausspielungen, die niemand gesehen hat. Manche mögen behaupten, das sei bei Display Bannern üblich. Dann kann man als Anbieter von TV-Werbung auch behaupten, mein Fernsehspot hatte 40 Mio. Impressionen – aber nur 10% davon waren wirklich „sichtbare Impressionen“, also in der Realität gesehene, denn 90% der Fernseher waren ausgeschaltet. Übrigens: auch bei Google Ads werden die Kennzahlen modelliert – auch hier zeigt unsere Erfahrung, dass die Werte tendenziell deutlich besser ausfallen als die überprüfbaren Daten.</p>



<h3 class="wp-block-heading"><strong>Daten richtig analysieren</strong></h3>



<p>Über Datenanalyse könnte man ein ganzes Buch schreiben. Ich möchte an der Stelle nur zwei Beispiele für&nbsp;<strong>Fehlinterpretationen</strong>&nbsp;aufzeigen:&nbsp;</p>



<p>Bei einer Display Ads Kampagne hatten wir als Zielgruppe weiblich 25-40 J. hinterlegt und diese auch entsprechend erreicht. Nach einigen Tagen haben wir genauer analysiert, wo die Anzeigen ausgeliefert wurden – nämlich in Spiele Apps für Kinder. Die benutzen das Handy der Mama und klicken versehentlich auf die Anzeige, wodurch Kosten entstehen. Vermeintlich wurde die Zielgruppe erreicht, bei genauem Überprüfen aber dann doch nicht.</p>



<p><em>Tipp:&nbsp;</em></p>



<p><em>Bei Google Ads Display Ads den Reiter Placements genau analysieren. Dort bekommt man eine Liste mit Webseiten, mobilen Apps und Videos präsentiert. Nicht passende kann man dort nach&nbsp;</em><strong><em>Überprüfung</em></strong><em>&nbsp;ausschließen. Im Internet gibt es auch vorgefertigte Listen um bspw. Dating- oder Spieleseiten auszuschließen. Expertentipp: Auch automatisierte&nbsp;</em><strong><em>Skript-Lösungen</em></strong><em>&nbsp;sind möglich.</em></p>



<p>Das andere Beispiel bezieht sich auf einen B2B-Kunden. Wenn nicht genügend Leads zur Optimierung erzielt werden, wird häufig auf&nbsp;<strong>Soft-Conversions</strong>&nbsp;wie Sitzungsdauer zurückgegriffen und optimiert. Das bedeutet, dass bspw. eine Verweildauer von 60 Sekunden auf der Webseite als Conversion getrackt und anschließend auf diese Conversion optimiert wird. Bei genauerer Analyse ist aufgefallen, dass sich viele Studenten auf der Webseite über das Thema informieren und entsprechend lange auf der Seite aufhalten. Der Algorithmus von Google folgerte daher daraus, es wäre sinnvoll auf Studenten zu optimieren, die jedoch überhaupt nicht zur Zielgruppe gehören. Das&nbsp;<strong>Conversion-Tracking</strong>&nbsp;haben wir bereinigt und Studenten bei den Anzeigenschaltungen ausgeschlossen.</p>



<p><em>Tipp:</em></p>



<p><em>Tracking regelmäßig hinterfragen. Nur mit der richtigen Datenbasis kann man auch richtig optimieren.</em></p>



<p>Ein lückenloses Tracking und damit&nbsp;<strong>hundertprozentig richtige Daten</strong>&nbsp;wird man im Marketing nie erreichen. Aber man kann sich annähern. Mit dem Wissen, dass Agenturen und Plattformen meist nicht objektiv sind, sondern Daten erheblich positiver auslegen als sie sind, sollte man die Kennzahlen kritisch hinterfragen.&nbsp;<strong>Werbeversprechen</strong>&nbsp;von Agenturen wie ROAS +300% sind entweder falsch, nicht überprüfbar oder nicht adaptierbar und damit&nbsp;<strong>wenig seriös</strong>.</p>



<p>Sie brauchen Unterstützung im Bereich SEA, Social Media Marketing, Tracking oder Datenanalyse? Kommen Sie gerne auf uns zu!&nbsp;&nbsp;</p>



<p>Fragen oder Kritik zum Artikel sind willkommen!</p>
<p>The post <a href="https://www.adtraffic.de/in-data-we-trust-koennen-wir-den-daten-der-online-marketing-plattformen-vertrauen/">In Data We Trust? – können wir den Daten der Online Marketing Plattformen vertrauen?</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Ranking Performance-Marketing 2022</title>
		<link>https://www.adtraffic.de/ranking-performance-marketing-2022/</link>
		
		<dc:creator><![CDATA[pp_admin]]></dc:creator>
		<pubDate>Sun, 10 Apr 2022 12:28:02 +0000</pubDate>
				<category><![CDATA[Allgemein]]></category>
		<guid isPermaLink="false">https://www.adtraffic.de/?p=102</guid>

					<description><![CDATA[<p>Der Wettbewerb unter den Onlinemarketing-Agenturen wird auch im nächsten Jahr weiter zunehmen und die Werbekunden werden umsichtiger. Gleichzeitig rüsten sich die Vermarkter für die datengeschützte Zukunft mit teils undurchsichtigen Produkten und Werbeformen. Wir stellen uns dieser unvermeidbaren Entwicklung in eine immer intransparentere Online-Werbewelt. Als spezialisierte Experten in den Bereichen SEA, SMA und Tracking sehen wir [&#8230;]</p>
<p>The post <a href="https://www.adtraffic.de/ranking-performance-marketing-2022/">Ranking Performance-Marketing 2022</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Der Wettbewerb unter den Onlinemarketing-Agenturen wird auch im nächsten Jahr weiter zunehmen und die Werbekunden werden umsichtiger. Gleichzeitig rüsten sich die Vermarkter für die datengeschützte Zukunft mit teils undurchsichtigen Produkten und Werbeformen.</p>



<p>Wir stellen uns dieser unvermeidbaren Entwicklung in eine immer intransparentere Online-Werbewelt. Als spezialisierte Experten in den Bereichen SEA, SMA und Tracking sehen wir unsere Aufgabe vor allem darin, unseren Kunden die notwendige Transparenz weitgehend zu erhalten. Das erreichen wir unter anderem mithilfe von Automatisierung, Datenmodellierung und individuellen Reportings.</p>



<h2 class="wp-block-heading">Kompakt greifbar</h2>



<p>Unsere Idee und Erfahrung sowie unsere Leistung und Herangehensweise haben wir mit Unterstützung unseres Partners pixelperfektion in unserer neuen Unternehmensbroschüre kompakt greifbar gemacht. Gerne senden wir Ihnen ein Exemplar auf Anfrage zu.</p>



<p>Parallel dazu haben wir am diesjährigen „Ranking Performance-Marketing 2022“ teilgenommen. Dazu hat der Münchner HighText Verlag[2] von 70 Agenturen die im Jahr 2021 verwalteten Performance-Marketing-Budgets zusammengetragen und die Ergebnisse online veröffentlicht. [1]</p>



<p>Die adtraffic konnte sich mit einem Gesamtbudget von 12,3 Mio. Euro einen guten Platz im oberen Mittelfeld des deutschlandweiten Rankings sichern. In unserem Spezialgebiet “Search Engine Advertising” erreichten wir sogar Platz 19 von 53 und verpassten so nur knapp das obere Drittel der teilnehmenden Agenturen. Auch für das “Teil-Ranking Automobil” qualifizierten wir uns und landeten mit 2,7 Mio. verwaltetem Werbebudget auf Platz 4 von 6.</p>



<h2 class="wp-block-heading">Große Budgets und unkonventionelle Arbeitsweise</h2>



<p>Wir freuen uns sehr über unsere Ergebnisse in den Rankings. Es zeigt, dass auch vermeintlich kleine Agenturen große Werbebudgets erfolgreich verwalten und performant skalieren können. Für uns ist es zudem eine Bestätigung unserer eher unkonventionellen Arbeitsweise: Unser Team arbeitet remote aus sechs Orten von Bruckmühl bis Göteborg und setzt bei vielen Detailaufgaben auf Automatisierung und Datenmodellierung. Damit sind wir in der Lage, auch sehr umfangreiche und feingliedrige Kampagnen in Werbekonten abzubilden und zu optimieren.</p>



<p><strong>Quellen:</strong></p>



<p>[1]&nbsp;<a href="https://www.onetoone.de/performance-ranking/">onetoone.de/performance-ranking/</a></p>



<p>[2] Der HighText Verlag veröffentlicht 14 verschiedene Unternehmens- und Branchen-Rankings der New Media Branche [3] und ist unter anderem Betreiber der Branchenportale iBusiness und ONEtoONE.</p>



<p>[3]&nbsp;<a href="https://www.ibusiness.de/rankings/">ibusiness.de/rankings/</a></p>
<p>The post <a href="https://www.adtraffic.de/ranking-performance-marketing-2022/">Ranking Performance-Marketing 2022</a> appeared first on <a href="https://www.adtraffic.de">adtraffic</a>.</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
