Implement Google remarketing
This commit is contained in:
@@ -27,6 +27,8 @@ namespace EP\EpProducts\Controller;
|
|||||||
* This copyright notice MUST APPEAR in all copies of the script!
|
* 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\Product;
|
||||||
use EP\EpProducts\Domain\Model\Reseller;
|
use EP\EpProducts\Domain\Model\Reseller;
|
||||||
use EP\EpProducts\Service\ResellerDataService;
|
use EP\EpProducts\Service\ResellerDataService;
|
||||||
@@ -154,46 +156,14 @@ class ResellerController extends ActionController
|
|||||||
|
|
||||||
$fileHandle = fopen('php://output', 'wb');
|
$fileHandle = fopen('php://output', 'wb');
|
||||||
|
|
||||||
fputcsv($fileHandle, [
|
if ($type === 'google') {
|
||||||
'id',
|
$csv = GoogleBusinessFeedCsvFormatter::format($data);
|
||||||
'availability',
|
} else {
|
||||||
'condition',
|
$csv = FacebookCatalogCsvFormatter::format($data);
|
||||||
'description',
|
|
||||||
'image_link',
|
|
||||||
'link',
|
|
||||||
'title',
|
|
||||||
'price',
|
|
||||||
'brand',
|
|
||||||
]);
|
|
||||||
|
|
||||||
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']);
|
foreach ($csv as $row) {
|
||||||
$description = strip_tags($description);
|
fputcsv($fileHandle, $row);
|
||||||
$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'
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose($fileHandle);
|
fclose($fileHandle);
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace EP\EpProducts\CsvFormatter;
|
||||||
|
|
||||||
|
class FacebookCatalogCsvFormatter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array $data
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function format(array $data)
|
||||||
|
{
|
||||||
|
$csv = [];
|
||||||
|
|
||||||
|
$csv[] = [
|
||||||
|
'id',
|
||||||
|
'availability',
|
||||||
|
'condition',
|
||||||
|
'description',
|
||||||
|
'image_link',
|
||||||
|
'link',
|
||||||
|
'title',
|
||||||
|
'price',
|
||||||
|
'brand',
|
||||||
|
];
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
$csv[] = [
|
||||||
|
$product['@id'],
|
||||||
|
$available > 0 ? 'in stock' : 'out of stock',
|
||||||
|
'new',
|
||||||
|
$description,
|
||||||
|
$product['images']['image'][0],
|
||||||
|
$product['link'],
|
||||||
|
$product['name'],
|
||||||
|
$minPrice . ' EUR',
|
||||||
|
'brand-epreisen'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $csv;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace EP\EpProducts\CsvFormatter;
|
||||||
|
|
||||||
|
class GoogleBusinessFeedCsvFormatter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param array $data
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public static function format(array $data)
|
||||||
|
{
|
||||||
|
$csv = [];
|
||||||
|
|
||||||
|
$csv[] = [
|
||||||
|
'Destination ID',
|
||||||
|
'OriginID',
|
||||||
|
'Title',
|
||||||
|
'Final URL',
|
||||||
|
'Image URL',
|
||||||
|
'Price',
|
||||||
|
];
|
||||||
|
|
||||||
|
foreach ($data['product'] as $product) {
|
||||||
|
$minPrice = 0;
|
||||||
|
|
||||||
|
foreach ($product['hotels']['hotel'] as $hotel) {
|
||||||
|
foreach ($hotel['dates']['date'] as $date) {
|
||||||
|
if ($minPrice === 0 || $date['minprice'] < $minPrice) {
|
||||||
|
$minPrice = $date['minprice'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$csv[] = [
|
||||||
|
$product['@id'],
|
||||||
|
$product['@id'],
|
||||||
|
$product['name'],
|
||||||
|
$product['link'],
|
||||||
|
$product['images']['image'][0],
|
||||||
|
$minPrice . '.00 EUR',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $csv;
|
||||||
|
}
|
||||||
|
}
|
||||||
+36
-8
@@ -66,11 +66,13 @@
|
|||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
},
|
},
|
||||||
fbPixelData: {
|
busProId: {
|
||||||
type: Object,
|
type: Number,
|
||||||
default () {
|
default: 0
|
||||||
return {}
|
},
|
||||||
}
|
nameInternal: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
},
|
},
|
||||||
daytrip: {
|
daytrip: {
|
||||||
type: Number,
|
type: Number,
|
||||||
@@ -93,7 +95,7 @@
|
|||||||
this.detailShow = false;
|
this.detailShow = false;
|
||||||
let query = {};
|
let query = {};
|
||||||
query[this.argumentPrefix + '[filterSettings]'] = this.filterSettings;
|
query[this.argumentPrefix + '[filterSettings]'] = this.filterSettings;
|
||||||
$.post(this.uris['dates'], query, (json) => {
|
$.post(this.uris['dates'], query, json => {
|
||||||
if (json.dates.length === 1) {
|
if (json.dates.length === 1) {
|
||||||
this.singleDate = true;
|
this.singleDate = true;
|
||||||
let dateRow = json.dates[0];
|
let dateRow = json.dates[0];
|
||||||
@@ -116,7 +118,7 @@
|
|||||||
this.detailShow = false;
|
this.detailShow = false;
|
||||||
let query = {};
|
let query = {};
|
||||||
query[this.argumentPrefix + '[product]'] = this.filterSettings;
|
query[this.argumentPrefix + '[product]'] = this.filterSettings;
|
||||||
$.post(this.uris['dateslist'], query, (json) => {
|
$.post(this.uris['dateslist'], query, json => {
|
||||||
if (json.dates.length === 1) {
|
if (json.dates.length === 1) {
|
||||||
this.singleDate = true;
|
this.singleDate = true;
|
||||||
let dateRow = json.dates[0];
|
let dateRow = json.dates[0];
|
||||||
@@ -151,12 +153,13 @@
|
|||||||
let query = {};
|
let query = {};
|
||||||
query[this.argumentPrefix + '[filterSettings]'] = this.filterSettings;
|
query[this.argumentPrefix + '[filterSettings]'] = this.filterSettings;
|
||||||
query[this.argumentPrefix + '[date]'] = dateUid;
|
query[this.argumentPrefix + '[date]'] = dateUid;
|
||||||
$.post(this.uris['pricetable'], query, (json) => {
|
$.post(this.uris['pricetable'], query, json => {
|
||||||
this.priceTableRows = json.priceTable;
|
this.priceTableRows = json.priceTable;
|
||||||
this.dateStart = dayjs(json.dateStart).format('DD.MM.YYYY');
|
this.dateStart = dayjs(json.dateStart).format('DD.MM.YYYY');
|
||||||
this.dateEnd = dayjs(json.dateEnd).format('DD.MM.YYYY');
|
this.dateEnd = dayjs(json.dateEnd).format('DD.MM.YYYY');
|
||||||
this.servicesIncluded = json.servicesIncluded;
|
this.servicesIncluded = json.servicesIncluded;
|
||||||
this.loading = false;
|
this.loading = false;
|
||||||
|
this.trackConversion();
|
||||||
EventBus.$emit('tableLoaded');
|
EventBus.$emit('tableLoaded');
|
||||||
}, 'json');
|
}, 'json');
|
||||||
},
|
},
|
||||||
@@ -179,6 +182,31 @@
|
|||||||
},
|
},
|
||||||
scrollToMain () {
|
scrollToMain () {
|
||||||
EventBus.$emit('scrollTo', '#main');
|
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 () {
|
created () {
|
||||||
|
|||||||
@@ -17,7 +17,8 @@
|
|||||||
}'
|
}'
|
||||||
argument-prefix='<ep:argumentPrefix pluginName="Ajax" />'
|
argument-prefix='<ep:argumentPrefix pluginName="Ajax" />'
|
||||||
:hotel-first="{f:if(condition: settings.hotelOnTop, then: 'true', else: 'false')}"
|
:hotel-first="{f:if(condition: settings.hotelOnTop, then: 'true', else: 'false')}"
|
||||||
:fb-pixel-data="{ productUid: <f:format.raw>{product.busProId}</f:format.raw>, nameInternal: '<f:format.raw>{product.nameInternal}</f:format.raw>' }"
|
:bus-pro-id="{product.busProId -> f:format.raw()}"
|
||||||
|
name-internal="{product.nameInternal -> f:format.raw()}"
|
||||||
:daytrip="{product.daytrip -> v:variable.convert(type: 'int')}"
|
:daytrip="{product.daytrip -> v:variable.convert(type: 'int')}"
|
||||||
inline-template>
|
inline-template>
|
||||||
<article>
|
<article>
|
||||||
@@ -235,7 +236,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<facebook-pixel :values="{ content_ids: [ fbPixelData.productUid ], content_name: fbPixelData.nameInternal, content_type: 'product' }"></facebook-pixel>
|
<facebook-pixel :values="{ content_ids: [ busProId ], content_name: nameInternal, content_type: 'product' }"></facebook-pixel>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
<f:link.action action="xml" arguments="{reseller: reseller}" target="_blank">Export XML</f:link.action>
|
<f:link.action action="xml" arguments="{reseller: reseller}" target="_blank">Export XML</f:link.action>
|
||||||
<h2>Gesamtexport CSV (Facebook)</h2>
|
<h2>Gesamtexport CSV (Facebook)</h2>
|
||||||
<f:link.action action="csv" arguments="{reseller: reseller}" target="_blank">Export CSV</f:link.action>
|
<f:link.action action="csv" arguments="{reseller: reseller}" target="_blank">Export CSV</f:link.action>
|
||||||
|
<h2>Gesamtexport CSV (Google)</h2>
|
||||||
|
<f:link.action action="csv" arguments="{reseller: reseller, type: 'google'}" target="_blank">Export CSV</f:link.action>
|
||||||
<h2>Einzelexport für Copy&Paste</h2>
|
<h2>Einzelexport für Copy&Paste</h2>
|
||||||
<ul>
|
<ul>
|
||||||
<f:for each="{products}" as="product">
|
<f:for each="{products}" as="product">
|
||||||
|
|||||||
Reference in New Issue
Block a user