WebSite X5Help Center

19 RéPONSES
Daniel W.
Daniel W.
User
Meilleur utilisateur du mois DEMeilleur utilisateur du mois EN

I don't know if I understood the problem correctly. Files can be uploaded to your own web server or web space using an FTP program or using the FTP window of WebSite X5.

-----

Lire plus
Posté le de Daniel W.
Raoul R.
Raoul R.
User
Auteur

PHP class for your exact feed

Save as:

/includes/klantenvertellen_feed.php

<?php
declare(strict_types=1);

final class KlantenVertellenFeed
{
private string $feedUrl;
private string $cacheFile;
private int $cacheTtlSeconds;

public function __construct(string $feedUrl, string $cacheFile, int $cacheTtlSeconds = 21600)
{
$this->feedUrl = $feedUrl;
$this->cacheFile = $cacheFile;
$this->cacheTtlSeconds = $cacheTtlSeconds;
}

/**
* @return array{
* locationName:string,
* averageRating:string,
* numberReviews:string,
* viewReviewUrl:string,
* reviews:array<int, array{
* author:string,
* city:string,
* rating:string,
* reviewBody:string,
* datePublished:string,
* language:string
* }>
* }
*/
public function getData(int $maxReviews = 3): array
{
$xml = $this->loadXml();

if (!$xml instanceof SimpleXMLElement) {
return [
'locationName' => 'ClubTaxi',
'averageRating' => '',
'numberReviews' => '',
'viewReviewUrl' => 'https://www.klantenvertellen.nl/reviews/1023381/clubtaxi'
'reviews' => [],
];
}

$data = [
'locationName' => trim((string) $xml->locationName),
'averageRating' => trim((string) $xml->averageRating),
'numberReviews' => trim((string) $xml->numberReviews),
'viewReviewUrl' => trim((string) $xml->viewReviewUrl),
'reviews' => [],
];

if (isset($xml->reviews->reviews)) {
$count = 0;

foreach ($xml->reviews->reviews as $reviewNode) {
$reviewBody = $this->extractReviewText($reviewNode);

$data['reviews'][] = [
'author' => trim((string) $reviewNode->reviewAuthor) ?: 'Klant',
'city' => trim((string) $reviewNode->city),
'rating' => trim((string) $reviewNode->rating),
'reviewBody' => $reviewBody,
'datePublished' => $this->normaliseDate((string) $reviewNode->dateSince),
'language' => trim((string) $reviewNode->reviewLanguage),
];

$count++;
if ($count >= $maxReviews) {
break;
}
}
}

return $data;
}

private function extractReviewText(SimpleXMLElement $reviewNode): string
{
if (!isset($reviewNode->reviewContent->reviewContent)) {
return '';
}

$oneLiner = '';
$opinion = '';

foreach ($reviewNode->reviewContent->reviewContent as $contentNode) {
$group = trim((string) $contentNode->questionGroup);
$value = trim((string) $contentNode->rating);

if ($group === 'DEFAULT_ONELINER' && $value !== '') {
$oneLiner = $value;
}

if ($group === 'DEFAULT_OPINION' && $value !== '') {
$opinion = $value;
}
}

// Prefer fuller opinion text; fall back to one-liner.
if ($opinion !== '') {
return $opinion;
}

return $oneLiner;
}

private function loadXml(): ?SimpleXMLElement
{
$xmlString = $this->getXmlString();

if ($xmlString === null || trim($xmlString) === '') {
return null;
}

libxml_use_internal_errors(true);
$xml = simplexml_load_string($xmlString);

return $xml instanceof SimpleXMLElement ? $xml : null;
}

private function getXmlString(): ?string
{
if ($this->isCacheValid()) {
$cached = @file_get_contents($this->cacheFile);
return $cached !== false ? $cached : null;
}

$fresh = $this->downloadFeed();
if ($fresh !== null) {
$this->writeCache($fresh);
return $fresh;
}

if (is_file($this->cacheFile)) {
$cached = @file_get_contents($this->cacheFile);
return $cached !== false ? $cached : null;
}

return null;
}

private function isCacheValid(): bool
{
return is_file($this->cacheFile)
&& filemtime($this->cacheFile) !== false
&& (time() - (int) filemtime($this->cacheFile) < $this->cacheTtlSeconds);
}

private function downloadFeed(): ?string
{
$context = stream_context_create([
'http' => [
'method' => 'GET',
'timeout' => 10,
'header' => implode("\r\n", [
'User-Agent: ClubTaxi Review Feed Reader/1.0',
'Accept: application/xml,text/xml,*/*;q=0.8',
]),
],
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
],
]);

$result = @file_get_contents($this->feedUrl, false, $context);

return $result !== false ? $result : null;
}

private function writeCache(string $xml): void
{
$dir = dirname($this->cacheFile);

if (!is_dir($dir)) {
@mkdir($dir, 0775, true);
}

@file_put_contents($this->cacheFile, $xml, LOCK_EX);
}

private function normaliseDate(string $date): string
{
$date = trim($date);

if ($date === '') {
return '';
}

try {
$dt = new DateTimeImmutable($date);
return $dt->format('Y-m-d');
} catch (Throwable $e) {
return '';
}
}
}

Homepage usage

Place this where you want the review block to appear:

<?php
require_once __DIR__ . '/includes/klantenvertellen_feed.php';

$kvFeed = new KlantenVertellenFeed(
'https://www.klantenvertellen.nl/v1/review/feed.xml?hash=o8st5h6aoduubpq'
__DIR__ . '/cache/klantenvertellen_feed.xml',
21600 // 6 hours
);

$kv = $kvFeed->getData(3);
?>

<section class="reviews-panel">
<h3>Beoordeeld op KlantenVertellen</h3>

<?php if ($kv['averageRating'] !== '' && $kv['numberReviews'] !== ''): ?>
<div class="reviews-score">
<span class="score"><?php echo htmlspecialchars($kv['averageRating'], ENT_QUOTES, 'UTF-8'); ?></span>
<span class="score-meta">/ 10 op basis van <?php echo htmlspecialchars($kv['numberReviews'], ENT_QUOTES, 'UTF-8'); ?> beoordelingen</span>
</div>
<?php endif; ?>

<p class="reviews-intro">
ClubTaxi wordt door klanten beoordeeld om betrouwbaarheid, stiptheid en comfortabele ritten.
</p>

<?php if (!empty($kv['reviews'])): ?>
<div class="review-quotes">
<?php foreach ($kv['reviews'] as $review): ?>
<blockquote class="review-quote">
<p>“<?php echo htmlspecialchars($review['reviewBody'], ENT_QUOTES, 'UTF-8'); ?>”</p>
<footer>
– <?php echo htmlspecialchars($review['author'], ENT_QUOTES, 'UTF-8'); ?>
<?php if ($review['city'] !== ''): ?>
uit <?php echo htmlspecialchars($review['city'], ENT_QUOTES, 'UTF-8'); ?>
<?php endif; ?>
<?php if ($review['rating'] !== ''): ?>
(<?php echo htmlspecialchars($review['rating'], ENT_QUOTES, 'UTF-8'); ?>/10)
<?php endif; ?>
</footer>
</blockquote>
<?php endforeach; ?>
</div>
<?php endif; ?>

<p class="reviews-link">
<a href="<?php echo htmlspecialchars($kv['viewReviewUrl'], ENT_QUOTES, 'UTF-8'); ?>" target="_blank" rel="noopener noreferrer">
Bekijk alle beoordelingen op KlantenVertellen
</a>
</p>
</section>

CSS

.reviews-panel {
max-width: 900px;
margin: 2rem auto;
padding: 1.5rem;
border: 1px solid #ddd;
border-radius: 12px;
background: #fff;
}

.reviews-panel h3 {
margin-top: 0;
margin-bottom: 0.75rem;
}

.reviews-score {
margin-bottom: 1rem;
line-height: 1.2;
}

.reviews-score .score {
font-size: 2.2rem;
font-weight: 700;
}

.reviews-score .score-meta {
display: block;
font-size: 1rem;
}

.reviews-intro {
margin-bottom: 1.25rem;
}

.review-quotes {
display: grid;
gap: 1rem;
}

.review-quote {
margin: 0;
padding: 1rem;
border-left: 4px solid #ccc;
background: #f8f8f8;
border-radius: 6px;
}

.review-quote p {
margin: 0 0 0.5rem 0;
}

.review-quote footer {
font-size: 0.95rem;
}

.reviews-link {
margin-top: 1.25rem;
}

.reviews-link a {
font-weight: 600;
text-decoration: none;
}

.reviews-link a:hover,
.reviews-link a:focus {
text-decoration: underline;
}

Dynamic JSON-LD from the same feed

This lets you keep your rating data automatically up to date.

<?php if ($kv['averageRating'] !== '' && $kv['numberReviews'] !== ''): ?>
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "ClubTaxi",
"url": "https://www.clubtaxi.nl",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "<?php echo htmlspecialchars($kv['averageRating'], ENT_QUOTES, 'UTF-8'); ?>",
"bestRating": "10",
"reviewCount": "<?php echo htmlspecialchars($kv['numberReviews'], ENT_QUOTES, 'UTF-8'); ?>"
}
}
</script>
<?php endif; ?>

There is also a code suggested by ChatGPT for filtering language. But hey, this is way over my head already : ) Thanks

Lire plus
Posté le de Raoul R.
Raoul R.
Raoul R.
User
Auteur

Thanks Daniel, I got that. But how to implement the feed.xml into the project, that it gets uploaded, to a proper folder so that bots know to crawl the feed. That is the thing.

Lire plus
Posté le de Raoul R.
Daniel W.
Daniel W.
User
Meilleur utilisateur du mois DEMeilleur utilisateur du mois EN

If I understood correctly, then the PHP code is probably saved in the file klantenvertellen.php (and not in the file feed.xml) and loaded into the "includes" directory on the web space.

The feed has the file extension .php - for WebSite X5 e.g. x5feed.php (RSS feed).

With WebSite X5, the RSS feed readers need the file x5feed.php and the review feed probably needs the file klantenvertellen.php - if I understood that correctly.

Lire plus
Posté le de Daniel W.
Raoul R.
Raoul R.
User
Auteur

I have not saved anything yet related to the feed.xml. But I looked at using the RSS feed tool as well. And my conclusion was, that I cannot for this purpose. If that is what you are saying, correct: we are on the same page.

Lire plus
Posté le de Raoul R.
Raoul R.
Raoul R.
User
Auteur

The fact that platforms do not allow embedding is a common thing, I do not agree but it is what it is. Hosted by Godaddy means to me that I do not want to experiment, cause they are experts in blaming the customer for things that go wrong. I like not to edit files via their dashboard. I think the conclusion is that the team looks at the above as a request to develope a utility widget for this purpose. Await respons from the team, thanks Daniel, sleep well : )

Lire plus
Posté le de Raoul R.
Daniel W.
Daniel W.
User
Meilleur utilisateur du mois DEMeilleur utilisateur du mois EN

The problem is probably that the PHP script wants to access a third-party website - klantenvertellen.nl - and is therefore blocked by the GoDaddy firewall.

Let's see if the Incomedia staff has a solution or just point you to GoDaddy support.

Maybe GoDaddy users have some tips on how to solve the problem.

I'll say goodnight!

-----

Lire plus
Posté le de Daniel W.
Raoul R.
Raoul R.
User
Auteur

to be clear, I did not upload anything yet, nothing got refused by godaddy. I cannot create an upload that fits the criteria given and described in the above. Thanks Daniel, but that widget is not creating the files that I think I need on the server as well. Await respons from the team.

Lire plus
Posté le de Raoul R.
Incomedia
Eric C.
Incomedia

Hello Raoul,
I could not understand the request unfortunately: could you clarify why uploading the file in question manually, as mentioned by Daniel initially, is not a viable option?

Lire plus
Posté le de Eric C.
Raoul R.
Raoul R.
User
Auteur

Because Godaddy gives me an headache if I use their dash, only way to protect myself against those robbers is to be able to say "I did not touch anything

But the question is: Can it be done with your software, or not? And if not, is it something you will be willing to develop?

Lire plus
Posté le de Raoul R.
Incomedia
Eric C.
Incomedia

Hello Raoul,
what do you mean by "their dash"?
Files can be manually uploaded through WebSite X5, the process mentioned by Daniel was showing the steps to follow in the software and not external tools.

Lire plus
Posté le de Eric C.
Raoul R.
Raoul R.
User
Auteur

and ofcourse, the real fight is: embedding the page by the platform. And I am fighting, with focus on the target.

Lire plus
Posté le de Raoul R.
Raoul R.
Raoul R.
User
Auteur

I have not tried it, but let's assume I can drop the file, it will be a txt file. Nothing else. As far as I know, there is no file as klantenvertellen.php , there is the css component (which I cannot create), no clue how I can follow your instructions, and come to the desired result. That the data gets crawled, and preferable a selection gets published on the site. Say the 3 or 4 latest in each language. I just do not see it as doable (for me). So it can be the way to do it, but not for me. 

Lire plus
Posté le de Raoul R.
Incomedia
Eric C.
Incomedia

Hello Raoul,
I'm afraid I may be misunderstanding something about this, perhaps you could provide more context as to what this file is for and what you are trying to achieve?

Lire plus
Posté le de Eric C.
Raoul R.
Raoul R.
User
Auteur

I shared the content of the last how to do it as given by ChatGpt, those steps would lead to a) latest reviews that gets crawled, connected to the firm because the feed gets crawled at the server from the firm (me), and b) creating of a css, I assume that is the file for publication on the site, and c) Dynamic JSON-LD from the same feed, in other words a self updating loop, where most recent reviews get crawled (via server), and published. 

I enclose full text of the steps I would need to undertake to make it happen. Embedding with an I frame and some Json-ld alongside would be enough for me, I trust the bots to be smart enough, to come to the same SEO result, but review platforms are known not to allow embedding.

Perfect — this is enough to make the parser exact for your feed structure.
The XML is nicely structured, and the key fields are now clear:

Top level:

  • averageRating
  • numberReviews
  • viewReviewUrl

Per review:

  • reviewAuthor
  • city
  • rating
  • dateSince
  • reviewLanguage

And inside each review:

  • reviewContent > reviewContent
  • with questionGroup
  • where the useful text is usually in:
    • DEFAULT_ONELINER
    • or DEFAULT_OPINION

So below is a cleaned-up, exact PHP version tailored to this KlantenVertellen feed.


1. PHP class for your exact feed

Save as:

/includes/klantenvertellen_feed.php

<?php
declare(strict_types=1);

finalclassKlantenVertellenFeed
{
privatestring$feedUrl;
privatestring$cacheFile;
privateint$cacheTtlSeconds;

publicfunction__construct(string$feedUrl, string$cacheFile, int$cacheTtlSeconds=21600)
{
$this->feedUrl =$feedUrl;
$this->cacheFile =$cacheFile;
$this->cacheTtlSeconds =$cacheTtlSeconds;
}

/**
* @return array{
* locationName:string,
* averageRating:string,
* numberReviews:string,
* viewReviewUrl:string,
* reviews:array<int, array{
* author:string,
* city:string,
* rating:string,
* reviewBody:string,
* datePublished:string,
* language:string
* }>
* }
*/
publicfunctiongetData(int$maxReviews=3): array
{
$xml= $this->loadXml();

if (!$xmlinstanceof SimpleXMLElement) {
return [
'locationName' => 'ClubTaxi',
'averageRating' => '',
'numberReviews' => '',
'viewReviewUrl' => 'https://www.klantenvertellen.nl/reviews/1023381/clubtaxi',
'reviews' => [],
];
}

$data= [
'locationName' => trim((string) $xml->locationName),
'averageRating' => trim((string) $xml->averageRating),
'numberReviews' => trim((string) $xml->numberReviews),
'viewReviewUrl' => trim((string) $xml->viewReviewUrl),
'reviews' => [],
];

if (isset($xml->reviews->reviews)) {
$count=0;

foreach ($xml->reviews->reviews as$reviewNode) {
$reviewBody= $this->extractReviewText($reviewNode);

$data['reviews'][] = [
'author' => trim((string) $reviewNode->reviewAuthor) ?: 'Klant',
'city' => trim((string) $reviewNode->city),
'rating' => trim((string) $reviewNode->rating),
'reviewBody' => $reviewBody,
'datePublished' => $this->normaliseDate((string) $reviewNode->dateSince),
'language' => trim((string) $reviewNode->reviewLanguage),
];

$count++;
if ($count>=$maxReviews) {
break;
}
}
}

return$data;
}

privatefunctionextractReviewText(SimpleXMLElement$reviewNode): string
{
if (!isset($reviewNode->reviewContent->reviewContent)) {
return'';
}

$oneLiner='';
$opinion='';

foreach ($reviewNode->reviewContent->reviewContent as$contentNode) {
$group=trim((string) $contentNode->questionGroup);
$value=trim((string) $contentNode->rating);

if ($group==='DEFAULT_ONELINER'&&$value!=='') {
$oneLiner=$value;
}

if ($group==='DEFAULT_OPINION'&&$value!=='') {
$opinion=$value;
}
}

// Prefer fuller opinion text; fall back to one-liner.
if ($opinion!=='') {
return$opinion;
}

return$oneLiner;
}

privatefunctionloadXml(): ?SimpleXMLElement
{
$xmlString= $this->getXmlString();

if ($xmlString===null||trim($xmlString) ==='') {
returnnull;
}

libxml_use_internal_errors(true);
$xml=simplexml_load_string($xmlString);

return$xmlinstanceof SimpleXMLElement ?$xml : null;
}

privatefunctiongetXmlString(): ?string
{
if ($this->isCacheValid()) {
$cached=@file_get_contents($this->cacheFile);
return$cached!==false?$cached : null;
}

$fresh= $this->downloadFeed();
if ($fresh!==null) {
$this->writeCache($fresh);
return$fresh;
}

if (is_file($this->cacheFile)) {
$cached=@file_get_contents($this->cacheFile);
return$cached!==false?$cached : null;
}

returnnull;
}

privatefunctionisCacheValid(): bool
{
returnis_file($this->cacheFile)
&&filemtime($this->cacheFile) !==false
&& (time() - (int) filemtime($this->cacheFile) < $this->cacheTtlSeconds);
}

privatefunctiondownloadFeed(): ?string
{
$context=stream_context_create([
'http' => [
'method' => 'GET',
'timeout' => 10,
'header' => implode("\r\n", [
'User-Agent: ClubTaxi Review Feed Reader/1.0',
'Accept: application/xml,text/xml,*/*;q=0.8',
]),
],
'ssl' => [
'verify_peer' => true,
'verify_peer_name' => true,
],
]);

$result=@file_get_contents($this->feedUrl, false, $context);

return$result!==false?$result : null;
}

privatefunctionwriteCache(string$xml): void
{
$dir=dirname($this->cacheFile);

if (!is_dir($dir)) {
@mkdir($dir, 0775, true);
}

@file_put_contents($this->cacheFile, $xml, LOCK_EX);
}

privatefunctionnormaliseDate(string$date): string
{
$date=trim($date);

if ($date==='') {
return'';
}

try {
$dt=new DateTimeImmutable($date);
return $dt->format('Y-m-d');
} catch (Throwable$e) {
return'';
}
}
}


2. Homepage usage

Place this where you want the review block to appear:

<?php
require_once __DIR__ .'/includes/klantenvertellen_feed.php';

$kvFeed=new KlantenVertellenFeed(
'https://www.klantenvertellen.nl/v1/review/feed.xml?hash=o8st5h6aoduubpq',
__DIR__ .'/cache/klantenvertellen_feed.xml',
21600// 6 hours
);

$kv= $kvFeed->getData(3);
?>

<sectionclass="reviews-panel">
<h3>Beoordeeld op KlantenVertellen</h3>

<?phpif ($kv['averageRating'] !==''&&$kv['numberReviews'] !==''): ?>
<divclass="reviews-score">
<spanclass="score"><?phpechohtmlspecialchars($kv['averageRating'], ENT_QUOTES, 'UTF-8'); ?></span>
<spanclass="score-meta">/ 10 op basis van <?phpechohtmlspecialchars($kv['numberReviews'], ENT_QUOTES, 'UTF-8'); ?> beoordelingen</span>
</div>
<?phpendif; ?>

<pclass="reviews-intro">
ClubTaxi wordt door klanten beoordeeld om betrouwbaarheid, stiptheid en comfortabele ritten.
</p>

<?phpif (!empty($kv['reviews'])): ?>
<divclass="review-quotes">
<?phpforeach ($kv['reviews'] as$review): ?>
<blockquoteclass="review-quote">
<p><?phpechohtmlspecialchars($review['reviewBody'], ENT_QUOTES, 'UTF-8'); ?></p>
<footer>
<?phpechohtmlspecialchars($review['author'], ENT_QUOTES, 'UTF-8'); ?>
<?phpif ($review['city'] !==''): ?>
uit <?phpechohtmlspecialchars($review['city'], ENT_QUOTES, 'UTF-8'); ?>
<?phpendif; ?>
<?phpif ($review['rating'] !==''): ?>
(<?phpechohtmlspecialchars($review['rating'], ENT_QUOTES, 'UTF-8'); ?>/10)
<?phpendif; ?>
</footer>
</blockquote>
<?phpendforeach; ?>
</div>
<?phpendif; ?>

<pclass="reviews-link">
<ahref="<?phpechohtmlspecialchars($kv['viewReviewUrl'], ENT_QUOTES, 'UTF-8'); ?>"target="_blank"rel="noopener noreferrer">
Bekijk alle beoordelingen op KlantenVertellen
</a>
</p>
</section>


3. CSS .reviews-panel {
max-width: 900px;
margin: 2remauto;
padding: 1.5rem;
border: 1pxsolid #ddd;
border-radius: 12px;
background: #fff;
}

.reviews-panelh3 {
margin-top: 0;
margin-bottom: 0.75rem;
}

.reviews-score {
margin-bottom: 1rem;
line-height: 1.2;
}

.reviews-score .score {
font-size: 2.2rem;
font-weight: 700;
}

.reviews-score .score-meta {
display: block;
font-size: 1rem;
}

.reviews-intro {
margin-bottom: 1.25rem;
}

.review-quotes {
display: grid;
gap: 1rem;
}

.review-quote {
margin: 0;
padding: 1rem;
border-left: 4pxsolid #ccc;
background: #f8f8f8;
border-radius: 6px;
}

.review-quotep {
margin: 000.5rem0;
}

.review-quotefooter {
font-size: 0.95rem;
}

.reviews-link {
margin-top: 1.25rem;
}

.reviews-linka {
font-weight: 600;
text-decoration: none;
}

.reviews-linka:hover,
.reviews-linka:focus {
text-decoration: underline;
}


4. Dynamic JSON-LD from the same feed

This lets you keep your rating data automatically up to date.

<?phpif ($kv['averageRating'] !==''&&$kv['numberReviews'] !==''): ?>
<scripttype="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "ClubTaxi",
"url": "https://www.clubtaxi.nl",
"aggregateRating": {
"@type": "AggregateRating",
"ratingValue": "<?phpechohtmlspecialchars($kv['averageRating'], ENT_QUOTES, 'UTF-8'); ?>",
"bestRating": "10",
"reviewCount": "<?phpechohtmlspecialchars($kv['numberReviews'], ENT_QUOTES, 'UTF-8'); ?>"
}
}
</script>
<?phpendif; ?>


5. A useful improvement for your feed: language filtering

Because your feed contains both Dutch and English reviews, you may want:

  • Dutch homepage → prefer Dutch reviews
  • English homepage → prefer English reviews

Here is the improved method for that.

Replace the getData() method with this version:

public function getData(int $maxReviews = 3, ?string $preferredLanguage = null): array
{
$xml = $this->loadXml();

if (!$xml instanceof SimpleXMLElement) {
return [
'locationName' => 'ClubTaxi',
'averageRating' => '',
'numberReviews' => '',
'viewReviewUrl' => 'https://www.klantenvertellen.nl/reviews/1023381/clubtaxi'
'reviews' => [],
];
}

$data = [
'locationName' => trim((string) $xml->locationName),
'averageRating' => trim((string) $xml->averageRating),
'numberReviews' => trim((string) $xml->numberReviews),
'viewReviewUrl' => trim((string) $xml->viewReviewUrl),
'reviews' => [],
];

$allReviews = [];

if (isset($xml->reviews->reviews)) {
foreach ($xml->reviews->reviews as $reviewNode) {
$allReviews[] = [
'author' => trim((string) $reviewNode->reviewAuthor) ?: 'Klant',
'city' => trim((string) $reviewNode->city),
'rating' => trim((string) $reviewNode->rating),
'reviewBody' => $this->extractReviewText($reviewNode),
'datePublished' => $this->normaliseDate((string) $reviewNode->dateSince),
'language' => trim((string) $reviewNode->reviewLanguage),
];
}
}

if ($preferredLanguage !== null) {
$preferred = array_values(array_filter(
$allReviews,
static fn(array $review): bool => $review['language'] === $preferredLanguage
));

$fallback = array_values(array_filter(
$allReviews,
static fn(array $review): bool => $review['language'] !== $preferredLanguage
));

$allReviews = array_merge($preferred, $fallback);
}

$data['reviews'] = array_slice($allReviews, 0, $maxReviews);

return $data;
}

Then use:

Dutch homepage $kv = $kvFeed->getData(3, 'nl'); English homepage $kv = $kvFeed->getData(3, 'en');

That is a very nice touch for multilingual trust.


6. Best recommendation for your site

For ClubTaxi, I would do this:

  • homepage: 3 reviews, language matched
  • route pages: compact score block only
  • review page: 10–20 reviews from the same feed
  • JSON-LD: aggregate rating on homepage and maybe major landing pages

That gives you:

  • trust
  • freshness
  • no iframe problems
  • better SEO consistency
Lire plus
Posté le de Raoul R.
Incomedia
Eric C.
Incomedia

Hello Raoul,
we do not provide support when it comes to custom code, what I wanted to understand was the overall context of your request, as I did not understand what you are trying to implement.
You initially mentioned a review platform, are you trying to show reviews from this platform on your website?
Why was css referenced in your initial post together with the .xml file?
Thank you.

Lire plus
Posté le de Eric C.
Raoul R.
Raoul R.
User
Auteur

And Eric, and to all, what I most appreciate about Incomedia is that you are not sucking blood out of your customers. And those who think you do, because of expired credits, or an updated seperator of whatever, please come to terms with your self. I appeciate an Euro is less for me, than for somebody at the other end of the world. But: firms like Godaddy, Klantenvertellen and the list is long are waiting for you, with knife and fork. And they do not waste time with cooking, the like it raw and bloody.

Need to talk you or your team about hosting soon, my worry is performance. Only reason to stay with Godaddy is speed and everything in the green so to speak. I do hope you have the correct package for me.

Lire plus
Posté le de Raoul R.
Raoul R.
Raoul R.
User
Auteur

Hello Raoul,
we do not provide support when it comes to custom code, what I wanted to understand was the overall context of your request, as I did not understand what you are trying to implement.
You initially mentioned a review platform, are you trying to show reviews from this platform on your website?
Why was css referenced in your initial post together with the .xml file?
Thank you.

Yes, and also get it updated so things do not get outdated. I want to increase the Trust score so to speak to the max. It frustrates me that competition fake reviews, but do not get banned or flagged, perhaps because what they spend on Ads. So I need to beat them in another way.

My references contain the BS as I receive it dear Eric :)

For now: I will battle Klantenvertellen, make clear I will not be their diner. Thanks for trying to understand, and the answer is no. I understand that.

Lire plus
Posté le de Raoul R.