From 6fea91ae26456befcdfe18468180cf16a5e423d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bjo=CC=88rn=20Fromme?= Date: Fri, 3 May 2019 17:38:28 +0200 Subject: [PATCH] Implement Google remarketing --- .../Classes/Controller/ResellerController.php | 48 +++------------ .../FacebookCatalogCsvFormatter.php | 59 +++++++++++++++++++ .../GoogleBusinessFeedCsvFormatter.php | 47 +++++++++++++++ .../Assets/js/components/ProductDetail.vue | 44 +++++++++++--- .../Private/Templates/Product/Detail.html | 5 +- .../Private/Templates/Reseller/List.html | 2 + 6 files changed, 156 insertions(+), 49 deletions(-) create mode 100644 web/typo3conf/ext/ep_products/Classes/CsvFormatter/FacebookCatalogCsvFormatter.php create mode 100644 web/typo3conf/ext/ep_products/Classes/CsvFormatter/GoogleBusinessFeedCsvFormatter.php diff --git a/web/typo3conf/ext/ep_products/Classes/Controller/ResellerController.php b/web/typo3conf/ext/ep_products/Classes/Controller/ResellerController.php index ea50b557..211b4160 100644 --- a/web/typo3conf/ext/ep_products/Classes/Controller/ResellerController.php +++ b/web/typo3conf/ext/ep_products/Classes/Controller/ResellerController.php @@ -27,6 +27,8 @@ namespace EP\EpProducts\Controller; * This copyright notice MUST APPEAR in all copies of the script! ***************************************************************/ +use EP\EpProducts\CsvFormatter\FacebookCatalogCsvFormatter; +use EP\EpProducts\CsvFormatter\GoogleBusinessFeedCsvFormatter; use EP\EpProducts\Domain\Model\Product; use EP\EpProducts\Domain\Model\Reseller; use EP\EpProducts\Service\ResellerDataService; @@ -154,46 +156,14 @@ class ResellerController extends ActionController $fileHandle = fopen('php://output', 'wb'); - fputcsv($fileHandle, [ - 'id', - 'availability', - 'condition', - 'description', - 'image_link', - 'link', - 'title', - 'price', - 'brand', - ]); + if ($type === 'google') { + $csv = GoogleBusinessFeedCsvFormatter::format($data); + } else { + $csv = FacebookCatalogCsvFormatter::format($data); + } - foreach ($data['product'] as $product) { - $minPrice = 0; - $available = 0; - - foreach ($product['hotels']['hotel'] as $hotel) { - foreach ($hotel['dates']['date'] as $date) { - if ($minPrice === 0 || $date['minprice'] < $minPrice) { - $minPrice = $date['minprice']; - } - $available++; - } - } - - $description = preg_replace( "/\r|\n/", ' ', $product['description']); - $description = strip_tags($description); - $description = htmlspecialchars_decode($description); - - fputcsv($fileHandle, [ - $product['@id'], - $available > 0 ? 'in stock' : 'out of stock', - 'new', - $description, - $product['images']['image'][0], - $product['link'], - $product['name'], - $minPrice . ' EUR', - 'brand-epreisen' - ]); + foreach ($csv as $row) { + fputcsv($fileHandle, $row); } fclose($fileHandle); diff --git a/web/typo3conf/ext/ep_products/Classes/CsvFormatter/FacebookCatalogCsvFormatter.php b/web/typo3conf/ext/ep_products/Classes/CsvFormatter/FacebookCatalogCsvFormatter.php new file mode 100644 index 00000000..37c3ad86 --- /dev/null +++ b/web/typo3conf/ext/ep_products/Classes/CsvFormatter/FacebookCatalogCsvFormatter.php @@ -0,0 +1,59 @@ + 0 ? 'in stock' : 'out of stock', + 'new', + $description, + $product['images']['image'][0], + $product['link'], + $product['name'], + $minPrice . ' EUR', + 'brand-epreisen' + ]; + } + + return $csv; + } +} diff --git a/web/typo3conf/ext/ep_products/Classes/CsvFormatter/GoogleBusinessFeedCsvFormatter.php b/web/typo3conf/ext/ep_products/Classes/CsvFormatter/GoogleBusinessFeedCsvFormatter.php new file mode 100644 index 00000000..11fda3de --- /dev/null +++ b/web/typo3conf/ext/ep_products/Classes/CsvFormatter/GoogleBusinessFeedCsvFormatter.php @@ -0,0 +1,47 @@ + { + $.post(this.uris['dates'], query, json => { if (json.dates.length === 1) { this.singleDate = true; let dateRow = json.dates[0]; @@ -116,7 +118,7 @@ this.detailShow = false; let query = {}; query[this.argumentPrefix + '[product]'] = this.filterSettings; - $.post(this.uris['dateslist'], query, (json) => { + $.post(this.uris['dateslist'], query, json => { if (json.dates.length === 1) { this.singleDate = true; let dateRow = json.dates[0]; @@ -151,12 +153,13 @@ let query = {}; query[this.argumentPrefix + '[filterSettings]'] = this.filterSettings; query[this.argumentPrefix + '[date]'] = dateUid; - $.post(this.uris['pricetable'], query, (json) => { + $.post(this.uris['pricetable'], query, json => { this.priceTableRows = json.priceTable; this.dateStart = dayjs(json.dateStart).format('DD.MM.YYYY'); this.dateEnd = dayjs(json.dateEnd).format('DD.MM.YYYY'); this.servicesIncluded = json.servicesIncluded; this.loading = false; + this.trackConversion(); EventBus.$emit('tableLoaded'); }, 'json'); }, @@ -179,6 +182,31 @@ }, scrollToMain () { EventBus.$emit('scrollTo', '#main'); + }, + trackConversion () { + const dataLayer = window.dataLayer || []; + dataLayer.push({ + 'google_tag_params': { + 'travel_destid': this.busProId, + 'travel_originid': this.busProId, + 'travel_pagetype': 'offerdetails', + 'travel_startdate': this.dateStart, + 'travel_enddate': this.dateEnd, + 'travel_totalvalue': this.calculateMinPriceFromPriceTable() + '.00 EUR' + } + }); + }, + calculateMinPriceFromPriceTable () { + let minPrice = 0; + for (let index in this.priceTableRows) { + if (!this.priceTableRows.hasOwnProperty(index)) { + continue; + } + if (minPrice === 0 || this.priceTableRows[index].roomPrice < minPrice) { + minPrice = this.priceTableRows[index].roomPrice; + } + } + return minPrice; } }, created () { diff --git a/web/typo3conf/ext/ep_theme/Resources/Private/Templates/Product/Detail.html b/web/typo3conf/ext/ep_theme/Resources/Private/Templates/Product/Detail.html index e8a6c7db..8107377a 100644 --- a/web/typo3conf/ext/ep_theme/Resources/Private/Templates/Product/Detail.html +++ b/web/typo3conf/ext/ep_theme/Resources/Private/Templates/Product/Detail.html @@ -17,7 +17,8 @@ }' argument-prefix='' :hotel-first="{f:if(condition: settings.hotelOnTop, then: 'true', else: 'false')}" - :fb-pixel-data="{ productUid: {product.busProId}, nameInternal: '{product.nameInternal}' }" + :bus-pro-id="{product.busProId -> f:format.raw()}" + name-internal="{product.nameInternal -> f:format.raw()}" :daytrip="{product.daytrip -> v:variable.convert(type: 'int')}" inline-template>
@@ -235,7 +236,7 @@ - +
diff --git a/web/typo3conf/ext/ep_theme/Resources/Private/Templates/Reseller/List.html b/web/typo3conf/ext/ep_theme/Resources/Private/Templates/Reseller/List.html index 9b1d1400..4159824e 100644 --- a/web/typo3conf/ext/ep_theme/Resources/Private/Templates/Reseller/List.html +++ b/web/typo3conf/ext/ep_theme/Resources/Private/Templates/Reseller/List.html @@ -14,6 +14,8 @@ Export XML

Gesamtexport CSV (Facebook)

Export CSV +

Gesamtexport CSV (Google)

+ Export CSV

Einzelexport für Copy&Paste