Video sitemap from contentblocks video player

Hello I need to create a sitemap for videos but the videos are inside a videoplayer block in contentblocks.

Each video had this schema, so I got the necessary data for the sitemap:

<script type="application/ld+json">
    {
        "@context": "http://schema.org",
        "@type": "VideoObject",
        "name": "[[+videoName]]",
        "description": "[[+videoDescription]]",
        "thumbnailUrl": "[[+videoThumbnailUrl]]",
        "uploadDate": "[[+videoUploadDate]]",
        "duration": "[[+videoDuration]]",
        "contentUrl": "[[+videoUrl]]",
        "embedUrl": "[[+videoEmbedUrl]]",
        "interactionCount": "[[+videoCount]]"
    },
    "publisher": {
      "@type": "Organization",
      "name": "[[+site_name]]",
      "logo": {
        "@type": "ImageObject",
        "url": "https://www.site.com/assets/img/logo/1van1man-logo.png",
        "width": 200,
        "height": 65
      }
    }
</script>

I created a div wiht the necessary data structure so I can get the data already builded to move it into the XML file.


<div class="videoSitemap" style="display: none;">
    <url>
        <loc>https://www.example.com/video-page</loc>
        <video:video>
            <video:thumbnail_loc>[[+videoThumbnailUrl]]</video:thumbnail_loc>
            <video:title>[[+videoName]]</video:title>
            <video:description>[[+videoDescription]]</video:description>
            <video:player_loc allow_embed="yes">[[+videoEmbedUrl]]</video:player_loc>
            <video:duration>[[+videoDuration]]</video:duration>
            <video:publication_date>[[+videoUploadDate]]</video:publication_date>
        </video:video>
    </url>
</div>

The problem is that I can’t get this content directly from the database, not sure where contentblocks is saving this data. I tried to get the data in different ways but no good luck.
If anyone can give me an idea about how to do it will be good, thanks!

The structured data is stored in the column “properties” of the resource.

There exists the snippet cbGetFieldContent to read the contentblock data of a certain type.

@halftrainedharry mate thanks, I think that can easily solve my problem.
I’ll play a bit and see but thank you very much for your help.
:+1:

@halftrainedharry hello mate. Testing the snippet it works but it’s retrieving data from specific resources, in that case I’ll need to know the resources ID’s something that I don’t know now, some pages has videos some doesn’t.

In this case I need to scan the whole site and get the video data if exist, so probably using pdoResources and use this extra to filter the results might work?

How might be the implementation or what do you think, any other idea?
Cheers!

Yes, you probably have to loop through all the resource to check if they contain a contentblock of a certain type.


It’s probably best to write a custom snippet and then use $modx->runSnippet() to run “cbGetFieldContent”.

You could use xPDO and $modx->getCollection() to loop through the resources. Or if you choose to use pdoResources, select the return type “data” so that you can handle the result with PHP:

$resources = $modx->runSnippet("pdoResources", [
    ...
    "return" => "data"
]);

Trying to build the code but I’m a bit stuck here, it’s not returning anything yet:

The field 46 is the video block inside contentblocks


<?php
$resources = $modx->getCollection('modResource'); 

if (!$resources) {
    return 'No resources found';
}

$matchingResourceIds = [];

foreach ($resources as $resource) {
    $resourceId = $resource->get('id');
    
    // Debug: Log each resource ID
    $modx->log(modX::LOG_LEVEL_ERROR, "Checking resource ID: {$resourceId}");
    
    // Run cbGetFieldContent on each resource
    $fieldValue = $modx->runSnippet('cbGetFieldContent', [
        'id' => $resourceId,
        'field' => 46
    ]);

    if (!empty($fieldValue)) {
        $matchingResourceIds[] = $resourceId;
    }
}

// Debug: Log final matching IDs
$modx->log(modX::LOG_LEVEL_ERROR, "Matching Resource IDs: " . implode(',', $matchingResourceIds));

return implode(',', $matchingResourceIds);

I don’t see an obvious reason why this snippet doesn’t work.
What is the value of $fieldValue? Always null or false?


Usually you don’t want to process resources that are either deleted or not yet published. So you might want to change this to

$resources = $modx->getCollection('modResource', ['published' => true, 'deleted' => false]);

If you only want to check if a certain block type exists on a resource, there is also the snippet cbHasField.