Support from Acquia helps fund testing for Drupal Acquia logo

Comments

Eric Heydrich created an issue. See original summary.

ChristophWeber’s picture

Version: 8.x-1.0-rc4 » 8.x-1.x-dev
Status: Active » Patch (to be ported)
FileSize
6.53 KB

Here's basic AggregateRating support, and an implementation in Organization to check how it works.

ChristophWeber’s picture

Status: Patch (to be ported) » Needs review
Eric Heydrich’s picture

Status: Needs review » Reviewed & tested by the community

Patch in #2 works for me. Tested also in Google's Structured Data Testing Tool.

Ruslan Piskarov’s picture

Hello @ChristophWeber. Can you explain how your path works with Voting API or any another related to "Rating" module and looking the current rating? Because I am not sure how it works and seems like the static values.
If yes, and if you have time you can update your solution as described on https://makedrupaleasy.com/articles/drupal-8-how-get-your-star-ratings-g..., in the article describes one of the approaches, although not universal. Could you have a look?

ChristophWeber’s picture

@Ruslan: I haven't bothered to check VotingAPI and its [lack of] tokens in its current unstable state. I simply plugged a number into the node's metatags for RatingValue and checked the JSON-LD output to ascertain proper function of the patch.
The dearth of working tokens from VotingAPI should be addressed in their issue queue. Once my site build advances enough I will be over there too to push things along, but probably not before Christmas. At that time I also plan to look at your code in more depth.

Ruslan Piskarov’s picture

I just wanted to say that in this case, the site administrator will always set up 5 stars, and this is not a real user's rating. Ok.

Ruslan Piskarov’s picture

Status: Reviewed & tested by the community » Needs review
FileSize
3.52 KB

I have nothing against the patch provided by @ChristophWeber, I just want to add my version, which works fundamentally in a different way.
Actually, it works long time for my site https://makedrupaleasy.com/articles/drupal-8-how-get-your-star-ratings-g... and I am just uploading the path from my site.
What do you think about?

Also, I have updated README.txt

For enabling aggregateRating functionality
(read more on https://developers.google.com/search/docs/data-types/review),
the site should have enabled "Voting API" and any UI module related to "Voting API", for example,
Votingapi Widgets (https://www.drupal.org/project/votingapi_widgets) or
Fivestar (https://www.drupal.org/project/fivestar).
Ruslan Piskarov’s picture

Providing the new patch. In this patch, nothing shows in ld+json if the node didn't rate yet.

ChristophWeber’s picture

Status: Needs review » Reviewed & tested by the community

A few remarks:

  • Why attach a rating to article? (Unless perhaps you use article for a review-style post). AggregateRating values are most useful in LocalBusiness, Product and Recipe schemas.
  • I like the approach in the last patch as a stop-gap measure to actually pull dynamic rating values while VotingAPI matures (I may actually end up using it to get my site built without waiting for VotingAPI.). At the end of the day, however, the ball ought to be in VotingAPI's court which should provide working tokens like every other mainstream module does.
  • Ruslan's patch does not address the original issue of making an overall class available which individual schemas can subclass. Should be trivial to change.
  • Based on Eric Heydrich's testing I consider the patch in #2 as sufficient to answer the original request. Setting issue back to RTBC.
testii28’s picture

We are using https://www.drupal.org/project/likebtn for content rating. How can we add data (aggregate rating) to JSON with Schema.org Metatag module. I cannot find such an option.
Thanks.

Ruslan Piskarov’s picture

Hello @testii28.

I have never been used "Like Button" module. However, I think you can easily implement aggregate rating to JSON just creating the plugin and put it to your custom module.
Please have a look at https://makedrupaleasy.com/articles/drupal-8-how-get-your-star-ratings-g.... Just replace a few strings
from (my article uses the data stored by "Voting API")

   $query = \Drupal::database()->select('votingapi_result', 'v');
      $query->fields('v', ['type', 'function', 'value']);
      $query->condition('entity_type', 'node');
      $query->condition('entity_id', $node->id());
      $result = $query->execute();
      while ($row = $result->fetchAssoc()) {
        $results[$row['type']][$row['function']] = $row['value'];
      }

to the similar like

$results = likebtn_get_count($node, 'node');

of cource you should update all code related to the plugin.
I didn't tested the code, just want to show you the idea.

KarenS’s picture

I have been digging through Voting API and friends to see what we might do that would work across all voting api widgets.

First of all I don't like the idea of using a direct query. In most cases we want a service or at least a method from voting api. That way if anything changes in voting api our implementation doesn't need to worry about it.

I see \Drupal\votingapi\VoteResultFunctionManager which looks like something we can use. Something like the following should work (untested, see http://cgit.drupalcode.org/votingapi/tree/src/VoteResultFunctionManager.... and http://cgit.drupalcode.org/votingapi/tree/votingapi.services.yml?h=8.x-3.x):

$votingservice = \Drupal:service('plugin.manager.votingapi.resultfunction');
$results = $votingservice->getResults($entity_type_id, $entity_id);

To actually test this, we need to try out a few different widgets and make sure it works correctly across them. Especially since some votes are added, some are counted, and some are averaged. I found the following widgets that use voting api that seem to have functional D8 code:

https://www.drupal.org/project/rate (7, 8.x-dev)
https://www.drupal.org/project/fivestar (7, 8.x-dev)
https://www.drupal.org/project/like_and_dislike (7, 8.x-1.0-alpha2)
https://www.drupal.org/project/votingapi_widgets (8.x-1.0-alpha3)
https://www.drupal.org/project/vote_up_down (7, 8.x-1.0-alpha3)
https://www.drupal.org/project/likebtn (7, 8.x-2.13)*

These are obviously rough since they mostly don't have stable releases, but trying a few of them should ensure we have a solution that *should* work. I would omit likebtn since the code in that module is totally non-standard, probably because it's trying to incorporate an external service. So I don't think it's a good proxy for a solution that would generally work.

If people interested in this project could try these ideas out it would move this along.

KarenS’s picture

Status: Reviewed & tested by the community » Needs work
KarenS’s picture

Also my approach to this would be to create a simple aggregate tag that works if you hard-code values or find tokens that work but contains no logic. Then an extension that incorporates Voting API to try to pull votes from Voting API's storage, as in the above patch. So there would be two classes.

testii28’s picture

I have tried likebtn and rating stars are showing up in Google after approx. 1 week. They are using javascript solution but it is working.
https://www.yavego.com/sites/default/files/stars-voting.PNG

KarenS’s picture

I pulled in https://www.drupal.org/project/schema_metatag/issues/2903107#comment-124..., which provides a basic AggregateRating in (one where you have to hard-code all the values). We can use this issue to try out some ideas for extending it to work with Voting API as well as allowing hard-coded values.

Ruslan Piskarov’s picture

@KarenS, I agree with you. Better to use service instead of a direct query.
I am updating the patch because of a few my sites temporary use the patch and because probably it can be helpful for someone. Okay. This path never will be committed to the repo.

Also, I made review the latest changes in schema_metatag module and don't like a solution why we should allow to use static values (http://take.ms/Hw0Gg). This will not motivate the site owner to use an honest rating, and many sites will have 5 stars for all pages. Frankly speaking, some sites will have 5 stars, even if these sites do not use the rating at all. This is only my opinion, however, I believe, you understand this too.

Yes, we should extend the basic AggregateRating and probably add like this

    $moduleHandler = \Drupal::service('module_handler');
    if ($moduleHandler->moduleExists('votingapi')) {
      $this->votingapiEnabled = TRUE;
    }

to the basic AggregateRating class to avoid a static values. Or even remake the form and allow to use checkbox (enabled/disabled AggregateRating) instead of the exists fields.

Also, we should find a way to detect http://schema.org/AggregateRating and https://pending.schema.org/EndorsementRating, because for now no way to do it using $voting_service->getResults('node', $node->id());.

It is just my current ideas. I will have a look at coming days when will have some free time. And also I am going to test with others modules.

KarenS’s picture

"Static values" means there is a place to use tokens if there are any, so it's important to include that. The Five Star module has a token for the rating, but not for the count, for instance. And other modules may add tokens in the future. The tokens are the best solution since they absolutely will compute the right value always, where our attempt to compute it might not.

I have come up with a solution that I think will work that I will commit soon. It has an option to indicate if you want to fill in the fields yourself (to use tokens) or compute the values using VotingAPI. The VotingAPI solution is more complex than your code because each module that uses Voting API implements voting in a different way, and some of them also have multiple widgets where each individual widget implements things differently. They have different indexes, not always 'vote'. Some use 'points', or 'up', or 'down', or 'star5', etc. And not only the indexes but the result function vary. Some use vote_sum and other use vote_average. The up/down modules have a vote_sum for both 'up' and 'down' and you have to subtract the downs from the ups. So it's really complicated and you have to at a minimum know which voting module is being used.

I've tried out a number of voting modules to see if the solution will work across them. I'm sure I haven't found all the ways they might vary, but if I get the code committed people can report if there are any problems.

KarenS’s picture

Part of the reason this is so hard is that Voting API has a service to return results in a standard way, but none to return the actual rating or count. I think that would be a great feature, so I made a feature request. But there has been no work on that module in a very long time so that probably won't go anywhere.

  • KarenS committed 11f17b0 on 8.x-1.x
    Issue #2916438 by Ruslan P, ChristophWeber, KarenS, Eric Heydrich:...
KarenS’s picture

Ok, code is committed so people can try it out. We also need to add the Aggregate tag to pretty much all the primary objects, it applies to everything. So Organization, Person, Product, Event, Video, whatever else we have.

KarenS’s picture

Status: Needs work » Needs review
KarenS’s picture

This is a little backwards. I went ahead and committed the changes, but it still needs review.

ChristophWeber’s picture

I am testing the new code in the context of recipe, using VotingAPI and votingapi_widget. The UI for schema_recipe works, but ratingValue and ratingCount fields aren't populated on output.

KarenS’s picture

To do anything about this I need steps to reproduce, what settings are configured in your voting field for instance? You can also debug the $results array produced by votingapi to see if you see the right results there (just put print_r($results) in the code at that point). Then look at the votingapi_widgets function to see if the logic in the function makes sense for the way you have the field configured and the values you see in $results.

ChristophWeber’s picture

KarenS’s picture

Status: Needs review » Needs work

Needs to be re-rolled now that #2900164: Add tests (D8) is in.

KarenS’s picture

Came up with a new approach. I spent many hours screwing around with the VotingAPI integration. Voting API and its modules are in very rough shape, so much so that I could hardly get them to work well enough to even register a rating so I could use it. So the new solution is going to be the following (patch coming):

- The Schema Metatag module will have a basic AggregateRating tag that does nothing with Voting API. Simple input boxes for the rating, count, etc. If you find token that will work you can use them. Or you can manually input values on the individual nodes. Or you can create custom code to populate them from some other source. But this module won't care about any of that, just provide the simple fields.
- This simple aggregateRating field is added to most of the other objects: recipe, service, product, organization, person, image, video, etc.
- All of these new elements have tests that pass.

- A new Schema VotingAPI module will be a separate module that includes a warning that it is untested. It contains a more complex aggregate rating tag that attempts to deduce the rating using Voting API.
- This module adds a second aggregate rating tag to each object that has the simple type. So if this module is enabled you'll see both the simple option with simple text fields and one labeled Voting API where you can input the name of the module you're using for ratings.
- None of this can be tested because it requires voting api and multiple voting modules, none of which provide methods to populate votes so the tag can test that it works.
- I can get it working myself for a couple situations using Voting API widgets and Vote Up Down. But each of those has multiple ways they can be configured and they aren't even stable so they might or might not work depending on what release or tag you are using. At best it is a starting point that might work better if those modules get more fully developed.

KarenS’s picture

Status: Needs work » Needs review
FileSize
35.98 KB

And here's the patch.

  • KarenS committed 53bcd20 on 8.x-1.x
    Issue #2916438 by RuslanP, KarenS: Provide AggregateRating in main...
KarenS’s picture

Status: Needs review » Fixed
ChristophWeber’s picture

Good resolution, thank you! After messing around for hours this past weekend without conclusive results I wholeheartedly agree. As a general observation, for our production websites we regulalrly find ourselves coding custom tokens to provide dynamic output in metatags. Nothing new here.

DamienMcKenna’s picture

Title: Provide AggregateRating in main module » Provide AggregateRating in main module (D8)
Ruslan Piskarov’s picture

Status: Fixed » Needs review

Hello guys,

I just updated the module to 8.x-1.0 and enabled "Schema.org Votingapi".
Sorry, however, I am not sure it was fixed/implemented correctly. Please have a look my screenshots http://take.ms/4D682.

Another issue, I think not related to "AggregateRating"

On /admin/config/search/metatag and /admin/config/search/metatag/node__article 8 times I see: Notice: Undefined variable: tag_id in Drupal\metatag\MetatagManager->sortedGroupsWithTags() (line 207 of modules/contrib/metatag/src/MetatagManager.php).
http://take.ms/1ddcJ

On /admin/config/search/metatag/node__article section "AGGREGATERATING FOR VOTING API" is reapiting 8 times.
http://take.ms/XyjbU

Or something wrong on my side?

The last submitted patch, 2: schema_metatag-2916438-2.patch, failed testing. View results

The last submitted patch, 18: interdiff-2916438-9-18-do-not-test.diff, failed testing. View results

ChristophWeber’s picture

Status: Needs review » Fixed

I think it'd be better to open a new issue, rather than warming up this one, hence I am closing this one as fixed.
As to your problem: My first patch, and the subsequent one building on it, never presumed it would output aggregateRating outside of a parent type such as product, organization, recipe or such. Maybe the current implementation needs some safeguards, but that's for another discussion. Please open fresh, and hopefully more focused issues.

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

denizserhat’s picture

Τhe voting api I've added media types field but
The attached file (schema_metatag-SchemaArticleAggregateRating-2916438-18.patch) does not work with media type and makes the following errors:
"The website encountered an unexpected error. Please try again later."
"Error: Call to a member function id() on null in Drupal\schema_article\Plugin\metatag\Tag\SchemaArticleAggregateRating->output() (line 80 of .../modules/contrib/schema_metatag/schema_article/src/Plugin/metatag/Tag/SchemaArticleAggregateRating.php) #0 .../modules/contrib/metatag/src/MetatagManager.php(544): Drupal\schema_article\Plugin\metatag\Tag\SchemaArticleAggregateRating->output() #1 .../modules/contrib/metatag/src/MetatagManager.php(465): Drupal\metatag\MetatagManager->generateRawElements(Array, Object(Drupal\media\Entity\Media)) #2 /.../modules/contrib/metatag/metatag.module(461): Drupal\metatag\MetatagManager->generateElements(Array, Object(Drupal\media\Entity\Media)) #3 .../modules/contrib/metatag/metatag.module(114): metatag_get_tags_from_route() #4 .../core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(297): metatag_page_attachments(Array) #5 .../core/lib/Drupal/Core/Render/MainContent/HtmlRenderer.php(273): Drupal\Core\Render\MainContent\HtmlRenderer->invokePageAttachmentHooks(Array) #6
.............."