Problem/Motivation

After applying patch #3182969: Wrong property_type for schema_qa_page_main_entity I can now populate the fields for Q/A in the Schema.org metatags for FAQpage. The problem is that if you enable pivot the questions are formatted correctly, but the answers are not split up properly. The output looks like this:

{
    "@context": "https://schema.org",
    "@graph": [
        {
            "@type": "FAQPage",
            "mainEntity": [
                {
                    "@type": "Question",
                    "name": "This is a test meta q1",
                    "answerCount": "1",
                    "acceptedAnswer": {
                        "@type": "Answer",
                        "text": [
                            "This is a test meta answer 1",
                            "This is a test meta answer 2"
                        ],
                        "url": "https://mysite.com/en/test-1"
                    }
                },
                {
                    "@type": "Question",
                    "name": "This is a test meta q2",
                    "answerCount": "1",
                    "acceptedAnswer": {
                        "@type": "Answer",
                        "text": [
                            "This is a test meta answer 1",
                            "This is a test meta answer 2"
                        ],
                        "url": "https://mysite.com/en/test-1"
                    }
                }
            ]
        },
        {
            "@type": "WebPage"
        }
    ]
}

I believe the correct format should be:

{
    "@context": "https://schema.org",
    "@graph": [
        {
            "@type": "FAQPage",
            "mainEntity": [
                {
                    "@type": "Question",
                    "name": "This is a test meta q1",
                    "answerCount": "1",
                    "acceptedAnswer": {
                        "@type": "Answer",
                        "text": [
                            "This is a test meta answer 1"
                        ],
                        "url": "https://mysite.com/en/test-1"
                    }
                },
                {
                    "@type": "Question",
                    "name": "This is a test meta q2",
                    "answerCount": "1",
                    "acceptedAnswer": {
                        "@type": "Answer",
                        "text": [
                            "This is a test meta answer 2"
                        ],
                        "url": "https://mysite.com/en/test-1"
                    }
                }
            ]
        },
        {
            "@type": "WebPage"
        }
    ]
}

Steps to reproduce

1. Enable FAQPage for schema_metatags on a content-type
2. Create two multivalue long text fields for question and answer on the c-t
3. Configure settings for schema_metadate FAQ/QA page set @type to FAQPage, configure question as token [node:field_meta_question], configure and answer as token [node:field_meta_answer] and choose PIVOT.
4. Create a node with a title and two questions and answers
5. View node header and see the issue

Proposed resolution

TBD

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

joel_osc created an issue. See original summary.

Steppico’s picture

Hi, I'm having the same issue.
I had a look into the source code, and I noticed that we should add a "Pivot" option to the acceptedAnswer field to obtain the wanted result.
I tested this real quick by hardcoding it in my code, just so to follow my hunch, and it worked as intended.

If no one comes up with a solution before I do, I'll write a patch for this.

denizserhat’s picture

I still have not found a solution to the issue and issues have come up at google.com/test/rich-results. You can share the patch until a solution is found?

Steppico’s picture

Sorry for the late reply, I ended up working on other features.
I'll come back soon at this issue and commit a proper patch.

Steppico’s picture

@denizserhat,

I started working on this. If however you want a quick solution, you can create a custom module and add a hook_form_alter that creates a pivot to "acceptedAnswer".
Something like this:

function YOUR_MODULE_NAME_form_alter(&$form, \Drupal\Core\Form\FormStateInterface $form_state, $form_id) {
  if ($form_id == "your_form_id") {
    $form["field_meta_tags"]["widget"][0]["schema_qa_page"]["schema_qa_page_main_entity"]["acceptedAnswer"]["pivot"] = [
          '#type' => 'select',
          '#title' => 'Pivot',
          '#empty_option' => ' - ' . t('None') . ' - ',
          '#empty_value' => '',
          '#options' => [
            1 => t('Pivot'),
          ],
          '#description' => t('Combine and pivot multiple values to display them as multiple objects.'),
    ];
  }
}

It should work correctly, for now ✌️

lindsay.wils’s picture

Thanks for starting to look at this. I am also seeing this issue and hoping for a patch. I tried the hook_form_alter on both the meta tags settings form and the node form and this did look to give the desired result.

{
    "@context": "https://schema.org",
    "@graph": [
        {
            "@type": "FAQPage",
            "mainEntity": [
                {
                    "@type": "Question",
                    "name": "What is this?",
                    "answerCount": "1",
                    "acceptedAnswer": {
                        "@type": "Answer",
                        "text": "\u003Cp\u003EIT IS THIS - Bro ipsum dolor sit amet wheelie stunt ripper line death cookies backside couloir fully grind brain bucket hellflip hero face shots over the bars crank.\u003C/p\u003E"
                    }
                },
                {
                    "@type": "Question",
                    "name": "What is that?",
                    "answerCount": "1",
                    "acceptedAnswer": {
                        "@type": "Answer",
                        "text": "\u003Cp\u003EIT IS THAT - Bro ipsum dolor sit amet wheelie stunt ripper line death cookies backside couloir fully grind brain bucket hellflip hero face shots over the bars crank.\u003C/p\u003E"
                    }
                }
            ]
        }
    ]
}
IsaacOldwood’s picture

The hook_form_alter() in #5 worked for me although I did need to alter it to

$form["field_metatags"]["widget"][0]["schema_qa_page"]["schema_qa_page_main_entity"]["acceptedAnswer"]["pivot"] = [
avpaderno’s picture

Version: 8.x-2.1 » 8.x-2.x-dev
Related issues: -#3182969: Wrong property_type for schema_qa_page_main_entity
denizserhat’s picture

@lindsay.wils

Thanks for your reply

I don't know how to create a "custom module and add a hook_form_alter". For the time being I use 8.x-1.8.

adrienco88’s picture

For people who need this until this is patched in the module, I created this in a more dynamic form, so it can be used on all the forms that have the FAQ Schema and also to save the "pivot" value when you re-edit the node. In my case I needed the pivot for both accepted answer and suggested answer.

<?php

/**
 * Implements hook_form_alter().
 */
 function YOUR_MODULE_NAME_form_alter(&$form, $form_state, $form_id) {
  // schema meta-tag FAQ pivot answers (multiple)
  if(isset($form["field_metatags"]) &&  isset($form["field_metatags"]["widget"][0]["schema_qa_page"])) {
    $pivotField = [
      "pivot" => [
        '#type' => 'select',
        '#title' => 'Pivot',
        '#empty_option' => ' - ' . t('None') . ' - ',
        '#empty_value' => '',
        '#default_value' => '',
        '#options' => [
          1 => t('Pivot'),
        ],
        '#description' => t('Combine and pivot multiple values to display them as multiple objects.'),
      ]
    ];
    
    // check if we have the default values
    $qa_tags = [];
    $nodeEntity = $form_state->getformObject()->getEntity();
    $metatags = unserialize($nodeEntity->get('field_metatags')->value);
    if($metatags && isset($metatags['schema_qa_page_main_entity'])) {
      if(!empty($metatags['schema_qa_page_main_entity'])) {
        $qa_tags = unserialize($metatags['schema_qa_page_main_entity']);
      }
    }

    // define the field names that needs pivots
    $answer_fields = ['acceptedAnswer', 'suggestedAnswer'];
    $qa_page_field = $form["field_metatags"]["widget"][0]["schema_qa_page"]["schema_qa_page_main_entity"];
    
    // loop the fields that needs the pivot
    if(count($answer_fields)) {
      foreach($answer_fields as $field_name) {
        if( isset($qa_page_field[$field_name])) {
          // set the default value
          if(!empty($qa_tags) && !empty($qa_tags[$field_name]) && isset($qa_tags[$field_name]['pivot'])) {
            $pivotField['pivot']['#default_value'] = $qa_tags[$field_name]['pivot'];
          }
    
          // get the pivot field preffered position
          $answerFields = $qa_page_field[$field_name];
          $keys = array_keys($answerFields);
          $index = array_search( '@type', $keys );
          $pos = false === $index ? count( $answerFields ) : $index + 1;
    
          // set the "Pivot" option right after the @type field
          $newAnswerFields = array_merge(array_slice($answerFields, 0, $pos), $pivotField, array_slice($answerFields, $pos));
          $form["field_metatags"]["widget"][0]["schema_qa_page"]["schema_qa_page_main_entity"][$field_name] = $newAnswerFields;
        }
      }
    }
  }
}
?>
basby’s picture

Thanks! #10 works for me ... almost. I had to replace field_metatags with field_meta_tags.

lindsay.wils’s picture

Hello. Adding a related issue to this.

With the hook_form_alter alter in place, the JSON formatted schema is now correct. Though, if a comma "," is entered into any question or answer text, this seems to mess with the pivot and breaks the output up over a series of extra question and answer combinations.

Is anyone else seeing this issue? Would be great to get this resolved also if a patch is to be created.

Thanks in advance.

mrdalesmith’s picture

My version of the code in #10 is slightly more complex but will work whatever you've called your metatag fields and also works on the default configuration form.


/**
 * Implements hook_form_FORM_ID_alter().
 */
function YOUR_MODULE_form_metatag_defaults_edit_form_alter(&$form, FormStateInterface $form_state) {
  if (isset($form['schema_qa_page']['schema_qa_page_main_entity'])) {
    $entity = $form_state->getformObject()->getEntity();
    $qa_tags = [];
    if ($metatags = $entity->get('tags')) {
      if (isset($metatags['schema_qa_page_main_entity'])) {
        $qa_tags = unserialize($metatags['schema_qa_page_main_entity']);
      }
    }
    $subform = &$form['schema_qa_page']['schema_qa_page_main_entity'];

    YOUR_MODULE_set_pivot_fields($subform, $qa_tags);
  }
}

/**
 * Implements hook_form_alter().
 */
function YOUR_MODULE_form_alter(&$form, $form_state) {
  $formObject = $form_state->getformObject();

  if ($formObject instanceof ContentEntityForm) {
    $entity = $formObject->getEntity();
    if ($fields = YOUR_MODULE_get_metatag_fields($entity)) {
      foreach ($fields as $machine => $field) {

        // schema meta-tag FAQ pivot answers (multiple)
        if (isset($form[$machine]) && isset($form[$machine]['widget'][0]['schema_qa_page'])) {

          // check if we have the default values
          $qa_tags = [];
          $metatags = unserialize($entity->get($machine)->value);
          if ($metatags && isset($metatags['schema_qa_page_main_entity'])) {
            if (!empty($metatags['schema_qa_page_main_entity'])) {
              $qa_tags = unserialize($metatags['schema_qa_page_main_entity']);
            }
          }

          // Define the field names that needs pivots
          $qa_page_field = &$form[$machine]['widget'][0]['schema_qa_page']['schema_qa_page_main_entity'];
          YOUR_MODULE_set_pivot_fields($qa_page_field, $qa_tags);
        }
      }
    }
  }
}

/**
 * Helper to set the pivot field on the answer sub-type.
 *
 * @param array $qa_form
 *   The schema_qa_page_main_entity array of a form.
 * @param array $tags
 *   An array of default values.
 */
function YOUR_MODULE_set_pivot_fields(array &$qa_form, $tags = []) {
  foreach (['acceptedAnswer', 'suggestedAnswer'] as $field_name) {
    if (isset($qa_form[$field_name])) {

      $pivotField = [
        'pivot' => [
          '#type' => 'select',
          '#title' => 'Pivot',
          '#empty_option' => ' - ' . t('None') . ' - ',
          '#empty_value' => '',
          '#default_value' => '',
          '#options' => [
            1 => t('Pivot'),
          ],
          '#description' => t('Combine and pivot multiple values to display them as multiple objects.'),
        ]
      ];

      // set the default value
      if (!empty($tags) && !empty($tags[$field_name]) && isset($tags[$field_name]['pivot'])) {
        $pivotField['pivot']['#default_value'] = $tags[$field_name]['pivot'];
      }

      // Get the pivot field preferred position
      $answerFields = $qa_form[$field_name];
      $keys = array_keys($answerFields);
      $index = array_search('@type', $keys);
      $pos = FALSE === $index ? count($answerFields) : $index + 1;

      // set the 'Pivot' option right after the @type field
      $newAnswerFields = array_merge(array_slice($answerFields, 0, $pos), $pivotField, array_slice($answerFields, $pos));
      $qa_form[$field_name] = $newAnswerFields;
    }
  }
}

/**
 * Helper to obtain all metatag fields on an entity.
 *
 * @param EntityInterface $entity
 *   A Drupal content entity interface.
 *
 * @return array
 *   An array of field data keyed by field machine names.
 */
function YOUR_MODULE_get_metatag_fields(EntityInterface $entity) {
  $field_list = [];

  // Get a list of the field definitions on this entity.
  $definitions = $entity->getFieldDefinitions();

  // Iterate through all the fields looking for ones in our list.
  foreach ($definitions as $field_name => $definition) {
    // Get the field type, ie: metatag.
    $field_type = $definition->getType();

    // Check the field type against our list of fields.
    if (isset($field_type) && 'metatag' == $field_type) {
      $field_list[$field_name] = $definition;
    }
  }

  return $field_list;
}

this is obviously just a quick fix: I can't work out the notation of the Question and Answer types to work out how to correct get the pivot field set by the existing code.

damienmckenna’s picture

Let's see if this is still a problem after #2976935 lands.

hunchang’s picture

after apply the both https://www.drupal.org/project/schema_metatag/issues/2976935 & https://www.drupal.org/project/metatag/issues/3067803 patches the separator is working.
However, the answer still not split out properly.

Before apply #10 solution,

<script type="application/ld+json">{
    "@context": "https://schema.org",
    "@graph": [
        {
            "@type": "FAQPage",
            "mainEntity": [
                {
                    "@type": "Question",
                    "name": "q1",
                    "acceptedAnswer": {
                        "@type": "Answer",
                        "text": [
                            "a1",
                            "a2",
                            "a3"
                        ]
                    }
                },
                {
                    "@type": "Question",
                    "name": "q2",
                    "acceptedAnswer": {
                        "@type": "Answer",
                        "text": [
                            "a1",
                            "a2",
                            "a3"
                        ]
                    }
                },
                {
                    "@type": "Question",
                    "name": "q3",
                    "acceptedAnswer": {
                        "@type": "Answer",
                        "text": [
                            "a1",
                            "a2",
                            "a3"
                        ]
                    }
                }
            ]
        }
    ]
}</script>

after #10 solution

<script type="application/ld+json">{
    "@context": "https://schema.org",
    "@graph": [
        {
            "@type": "FAQPage",
            "mainEntity": [
                {
                    "@type": "Question",
                    "name": "q1",
                    "acceptedAnswer": {
                        "@type": "Answer",
                        "text": "a1"
                    }
                },
                {
                    "@type": "Question",
                    "name": "q2",
                    "acceptedAnswer": {
                        "@type": "Answer",
                        "text": "a2"
                    }
                },
                {
                    "@type": "Question",
                    "name": "q3",
                    "acceptedAnswer": {
                        "@type": "Answer",
                        "text": "a3"
                    }
                }
            ]
        }
    ]
}</script>

DeaOm made their first commit to this issue’s fork.

deaom’s picture

Status: Postponed » Needs review
StatusFileSize
new1.53 KB

It seems that the #2976935: Improve support for multi-value schema using Metatag's custom separator option did not solve the pivot issue on FAQ and that issue is also postponed due to #3067803: Use custom delimiter instead of commas for multiple values which is RTBC. There are two possible solutions, one is to add the pivot field to sub properties (which this patch/commit does and what the workarounds suggest), the other one would be to better handle the pivot item, when there is a main entity that has the pivot set. Not sure how that would work if you do not wanna have the pivot automatically set for all the sub properties.

liliplanet’s picture

I tried #17 patch, site error

<'ParseError: syntax error, unexpected token "else", expecting end of file in Composer\Autoload\includeFile() (line 248 of /home/mysite/public_html/modules/contrib/schema_metatag/src/Plugin/schema_metatag/PropertyTypeBase.php)/code>

damienmckenna’s picture

@liliplanet: I'm not seeing that error locally, can you please try again? Thank you.

damienmckenna’s picture

Component: Code » Existing structures
ghost of drupal past’s picture

StatusFileSize
new1.34 KB

This is a lovely patch. I have simplified a little and added a strict search to array_search.

ghost of drupal past’s picture

Title: Pivot on FAQ is not creating the correct format » Pivot on sub elements like images, FAQ answers etc
dmezquia’s picture

Patch #22 works for me OK.

Drupal 9.4.8,
schema_metatag 2.4

castor-designs’s picture

Patch works for me as well but definitely should be added to the main version of this module!

castor-designs’s picture

Second topic: As soon as your sentence e. g. in the answer has a comma in it it pivots as well. So if I use fields to populate this section e. g. like this: [term:field_faq:0],[term:field_faq:1],[term:field_faq:2] then as soon as a value of this field has a comma in it e. g. "How long have you been studying English, and what motivated you to start?" it will pivot that but it makes no sense of course.

So is there a way to prevent this?

borutpiletic’s picture

I can confirm, patch #22 solved the issue for me on FAQPage.

schema_metatag 2.4
Drupal core 9.5.9

damienmckenna’s picture

Version: 8.x-2.x-dev » 3.0.x-dev
Status: Needs review » Fixed
Parent issue: » #3367955: Plan for Schema Metatag 3.0.1
Related issues: +#3325539: Plan for Schema.org Metatag 8.x-2.5

Committed. Thank you!

damienmckenna’s picture

Castor-designs: Please see the changes from #2976935: Improve support for multi-value schema using Metatag's custom separator option that went into the 3.0.x branch; you'll need to upgrade to Metatag v2 in order to use it.

Status: Fixed » Closed (fixed)

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