Metatag module currently doesn't have any integration for importing meta tags through the Feeds module. Initial patch to follow.

UPD: Patch expects that source string will be in JSON format.
E.g.:
{"title":"title value","description":"description value",...}

Issue fork metatag-3011202

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:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

artematem created an issue. See original summary.

artematem’s picture

Patch expects that source string will be in JSON format.
E.g.:
{"title":"title value","description":"description value",...}

artematem’s picture

artematem’s picture

Issue summary: View changes
DamienMcKenna’s picture

Status: Active » Needs review
DamienMcKenna’s picture

Thanks for doing this work!

DamienMcKenna’s picture

Is there a better way of handling the input string rather than requiring it be a JSON-encoded string?

mitchems’s picture

In the 7.X version of Feeds with Metatag module installed you could import to the individual metatags.

Only local images are allowed.

Any plans to allow for this again?

opsdemon’s picture

Hi @artematem,

I'm trying to set the "canonical_url" metatag via Feeds and came across this issue and your patch.

I've incorporated the patch successfully and set up a new mapping in Feeds for the "metatags" column to the "field_metatags" field.
I next tried to import an article with the value for the "metatags" field in the csv set to a test url:
{"canonical_url":"https://www.drupal.org/project/metatag/issues/3011202"}

When I do the import I can see that it has just used the default value ("[node:url]"), ignoring the value from the csv.
I've also tried setting the metatag values for "title" and "description" as in your example and these didn't work either.

Please can you let me know if there is anything else that needs to be done for a successful import of metatags using this patch?

Your help is much appreciated.

Thanks,

Gerald.

opsdemon’s picture

Please ignore my previous comment.

The issue with the canonical url metatag was just to use the id ("canonical_url") instead of the name ("canonical"). The issue with the title and description metatags not updating was just a compilation error on my part.

The patch is working fine now. @artematem, thanks for the code!

selva.swamy@gmail.com’s picture

@DamienMcKenna Tested with patch in comment#3 and it is working as expected. I think if we do not require any tests this patch can be marked as RTBC.

Since the raw value for metatag are exported as JSON when using module like https://www.drupal.org/project/raw_formatter, I think JSON is ok as we can import multiple metatag values using single mapping.

However a check if the input is indeed JSON would be good. If not, a error can be thrown.

Could you let us know your thoughts as we need this patch for a project?

DamienMcKenna’s picture

Status: Needs review » Needs work

I think at the very least the input needs some protection to ensure the input is valid JSON; the plugin's comment also needs improvement (typo, wording).

selva.swamy@gmail.com’s picture

@DamienMcKenna Updated patch attached. I also ran phpcs for this code and fixed some minor coding standard issues. Please have a look.

selva.swamy@gmail.com’s picture

Status: Needs work » Needs review
selva.swamy@gmail.com’s picture

@DamienMcKenna Could you please review the patch in comment#13?

fbreckx’s picture

I'm not sure on how I should format the JSON results. I have a list of blogitems as in the excerpt below.
'blogMetaTitle' and 'blogMetaDesc' is for the metadata.

{
    "blogs": [
        {
            "blogItem": {
                "blogTitle": "7 tips om goed te slapen tijdens koude winternachten",
                "blogMetaTitle": "7 tips om goed te slapen tijdens koude winternachten | Dorsoo",
                "blogMetaDesc": "Tijdens koude winternachten daalt de slaapkamertemperatuur. Dat kan zorgen voor een slechte nachtrust. Wat kan u doen om goed te slapen? Lees onze 7 tips. ",
                "blogID": "835",
                "blogAlias": "/nl/blog/7-tips-goed-slapen-tijdens-koude-winternachten",
                "blogImageAlt": "7 tips om goed te slapen tijdens koude winternachten - Dorsoo"
            }
        }
    ]
}

I tried rewriting the result to get it in one field, but this doesn't seem right :)

{'title':'[title]','description':'[description]'}

"blogMetaDesc": "{'title':'7 tips om goed te slapen tijdens koude winternachten | Dorsoo','description':'Tijdens koude winternachten daalt de slaapkamertemperatuur. Dat kan zorgen voor een slechte nachtrust. Wat kan u doen om goed te slapen? Lees onze 7 tips. '}",

That results in an error that says the field can't contain more than one value.

What's the correct way?

DamienMcKenna’s picture

Status: Needs review » Needs work
Issue tags: +Needs tests

I don't know what data structures Feeds works with in D8 so I can't help, sorry.

This is where some test coverage would help.

fbreckx’s picture

@artematem, could you help me out please? I can't seem to structure my data feed the right way ...

artematem’s picture

@fbreckx, I believe this is because your whole feed is in JSON format.
You'll need to make it as a string in feed, something like that:
"blogMetaDesc": "\{'title':'7 tips om goed te slapen tijdens koude winternachten | Dorsoo','description':'Tijdens koude winternachten daalt de slaapkamertemperatuur. Dat kan zorgen voor een slechte nachtrust. Wat kan u doen om goed te slapen? Lees onze 7 tips. '\}"
And create your own target class from example in patch or add some pre-preprocess (e.g. str replace in Tamper) to convert string to JSON before passing to prepareValue().

fbreckx’s picture

Thanks for your help @artematem! So I modified my JSON feed to this:

{
    "blogs": [
        {
            "blogItem": {
                "blogTitle": "7 tips om goed te slapen tijdens koude winternachten",
                "blogImage": {
                    "src": "https://www.dorsoo.be/sites/default/files/blogberichten/Dorsoo-blog-tips-goed-slapen-koude-winternachten-1.jpg",
                    "alt": "7 tips om goed te slapen tijdens koude winternachten - Dorsoo",
                    "title": "7 tips om goed te slapen tijdens koude winternachten - Dorsoo"
                },
                "blogAuthor": "Nadja",
                "blogIsPinned": "",
                "blogCTA": "",
                "blogPoll": "",
                "blogTags": "Slaapkamer",
                "blogPublishedDate": "2020-01-27T09:43:51+01:00",
                "blogChangedDate": "2020-01-28T10:33:34+01:00";
                "blogMetaTitle": "\\{'title':'7 tips om goed te slapen tijdens koude winternachten | Dorsoo','description':'Tijdens koude winternachten daalt de slaapkamertemperatuur. Dat kan zorgen voor een slechte nachtrust. Wat kan u doen om goed te slapen? Lees onze 7 tips. '\\}",
                "blogID": "835",
                "blogAlias": "/nl/blog/7-tips-goed-slapen-tijdens-koude-winternachten",
                "blogSticky": "Niet waar"
            }
        }
    ]
            }

Views Data Export makes it hard to export the field blogMetaTitle the right way (the double backslash). But I guess Tamper can do the job.

What isn't clear to me: firstly you need to export it as a string in feed, but then you change it back to JSON?
Could you be a bit more specific?

So with this feed:

  • Tamper Find and Replace '\\' to '\''
  • More preprocessing with Tamper?

Thanks a bunch!

Just for your information: I'm migrating around 200 blogs from D7 to D8. This would come in handy ;)

Frank HH-germany’s picture

Hi, I'm a little confused.

Can I use the patch like this or do I still have to manually enter the targets in the code?

If the goals still have to be entered, where do they belong?

Then I'll get started and enter all the metategs and schema.org in the code and upload it here.

Greetings from Hamburg-Germany

---

Update
After I uploaded the patch when clicking on assignment the following error was displayed.

The website encountered an unexpected error. Please try again later.
Error: Class 'Drupal\feeds\Feeds\Target\Metatag' not found in Drupal\feeds\Entity\FeedType->getMappingTargets() (line 304 of modules/contrib/feeds/src/Entity/FeedType.php).

and

Fatal error: Cannot declare class Drupal\metatag\Feeds\Target\Metatag, because the name is already in use in .../web/modules/contrib/feeds/src/Feeds/Target/Metatag.php on line 44

Frank HH-germany’s picture

When troubleshooting, I noticed the following:

in all php files there are more entries from line 5 onwards.

Example Text.php:

<?php

namespace Drupal\feeds\Feeds\Target;

use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\feeds\FieldTargetDefinition;
use Drupal\feeds\Plugin\Type\Target\ConfigurableTargetInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;

Unfortunately I don't really know much about php.

Summit’s picture

Hi,

So we need feeds and feeds tamper to get Metatags from Drupal 7 install to Drupal 8 through Feeds?
greetings, Martijn

DamienMcKenna’s picture

@summit: Any reason to not just use the migrate system for doing the D7->D8 upgrade?

Summit’s picture

Hi Damien, Yes! A custom module what I used frequently (+- 800 times), doesn't have migrate integration.
For me as non-programmer is it a too deep learning curve to get this working with migrate, see this try thread; https://www.drupal.org/project/weblinks/issues/3128945

I use a lot specific meta tags within this contenttype. So it would be great to have a Metatag-Feeds solution, so I can import the D7 weblinks to D8 other contenttype with keeping the metatags!
greetings,Martijn

Summit’s picture

Hi, I tried patch #13, but I got the following error

PHP Fatal error:  Cannot declare class Drupal\metatag\Feeds\Target\Metatag, because the name is already in use in /modules/contrib/feeds/src/Feeds/Target/Metatag.php on line 43

What can I do to solve this problem please?
greetings, Martijn

Summit’s picture

Hi, Finally working patch #13

<?php

namespace Drupal\feeds\Feeds\Target;

use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\feeds\FieldTargetDefinition;
use Drupal\feeds\Plugin\Type\Target\FieldTargetBase;

/**
 * Defines a address field mapper.
 *
 * @FeedsTarget(
 *   id = "address",
 *   field_types = {"address", "address_country"}
 * )
 */
class Address extends FieldTargetBase {

  /**
   * {@inheritdoc}
   */
  protected static function prepareTarget(FieldDefinitionInterface $field_definition) {
   $definition = FieldTargetDefinition::createFromFieldDefinition($field_definition);
   if ($field_definition->getType() === 'address_country') {
     $definition->addProperty('value');
   }
   if ($field_definition->getType() === 'address') {
     $definition
       ->addProperty('langcode')
       ->addProperty('country_code')
       ->addProperty('administrative_area')
       ->addProperty('locality')
       ->addProperty('dependent_locality')
       ->addProperty('postal_code')
       ->addProperty('sorting_code')
       ->addProperty('address_line1')
       ->addProperty('address_line2')
       ->addProperty('organization')
       ->addProperty('given_name')
       ->addProperty('additional_name')
       ->addProperty('family_name');
    }
    return $definition;
  }
}

I had to change the first line
from +namespace Drupal\metatag\Feeds\Target;
to ++namespace Drupal\feeds\Feeds\Target;

greetings, Martijn

damondt’s picture

@Summit You don't want to put a class in another module's namespace.
@kswamy Your patch would address my specific use case (json encoded values), but a better way to go about this would be with multiple properties you can map to. There's an example of this in Drupal\feeds\Feeds\Target\Image

Summit’s picture

Hi Damondt,

I understand, but it didn't work without it. Then I got PHP Fatal error: Cannot declare class Drupal\metatag\Feeds\Target\Metatag, because the name is already in use in /modules/contrib/feeds/src/Feeds/Target/Metatag.php on line 43
I am not a good enough programmer to do it correctly may be..
greetings, Martijn

damondt’s picture

I'm attaching a patch that adds a Feeds Target to handle metatag fields. It provides mapping targets for any tags in the "basic" group. The improvements over the last patch include the ability to map to individual tag fields and being source format agnostic. Only the tags in the basic group are provided as targets at the moment as adding targets for all of them is unmanageable due to this issue.

There is a plan to make a generic field target for feeds, but that still won't for metatag field with the way the data is stored as a serialized array.

To Test:
1. Create a feed type mapping to a bundle with a metatag field.
2. Go to the "Mapping" tab of the feed type and select the metatag field as a target
3. Note that all tags in the Basic group are available to map to.
4. Map sources to these targets and note that the import works.

Screenshot

damondt’s picture

damondt’s picture

Status: Needs work » Needs review
ivnish’s picture

Status: Needs review » Reviewed & tested by the community

#30 works for me

ivnish’s picture

Please commit

introfini’s picture

#30 works, thanks!

andypost’s picture

DamienMcKenna’s picture

This is definitely a step in the right direction, but I don't like how it's currently limited by problems in the Feeds UI, specifically #3173943: Make target selection same height as source selection in mapping form, so I'm not willing to commit it as-is. I would suggest reworking this patch to allow all meta tags, like the D7 version has, and then collaborating on improving the Feeds UI.

someshver’s picture

I have updated the patch to support OG metatag and Advanced tags.

Summit’s picture

Hi,
Can this patch be used to import meta tags through feeds in Drupal 10?
Thanks for your reply in advance!
Greetings, Martijn

DamienMcKenna’s picture

That is the intention, yes.

trickfun’s picture

I apply this patch on
metatag 2.0.0
feed 8.x-3.0-beta4

i get this error

TypeError: array_merge(): Argument #2 must be of type array, null given in array_merge() (line 40 of modules/contrib/metatag/src/Feeds/Target/Metatag.php).
Drupal\metatag\Feeds\Target\Metatag::prepareTarget(Object) (Line: 57)
Drupal\feeds\Plugin\Type\Target\FieldTargetBase::targets(Array, Object, Array) (Line: 305)
Drupal\feeds\Entity\FeedType->getMappingTargets() (Line: 105)
Drupal\feeds\Form\MappingForm->buildForm(Array, Object, Object)
call_user_func_array(Array, Array) (Line: 536)
Drupal\Core\Form\FormBuilder->retrieveForm('feeds_mapping_form', Object) (Line: 283)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 592)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 121)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 182)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 76)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 106)
Drupal\page_cache\StackMiddleware\PageCache->pass(Object, 1, 1) (Line: 85)
Drupal\page_cache\StackMiddleware\PageCache->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object, 1, 1) (Line: 704)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)

i think feed integration is very important feature to have.
thank you

mNigma07’s picture

Drupal 10
metatag 2.0.0

#38 Metatag.php replace lines 36-38 with:
$metatag_basic = $metatag_manager->sortedGroupsWithTags()['basic']['tags'] ?? [];
$metatag_og = $metatag_manager->sortedGroupsWithTags()['open_graph']['tags'] ?? [];
$metatag_advanced = $metatag_manager->sortedGroupsWithTags()['advanced']['tags'] ?? [];

djschoone’s picture

#42 works. Will look into making a patch

djschoone’s picture

#42 works. Made it into a new patch applied to

  • Drupal 10.2.4
  • Metatag 2.0.0
  • Feeds 8.x-3.0-beta4
Jared Nolt’s picture

Patch #44 worked great in mapping Basic and Advanced schema fields! Would it be possible to make the Product Schema fields available to be mapped and imported also?

DamienMcKenna’s picture

Version: 8.x-1.x-dev » 2.0.x-dev

For complex setups you might look at Schema.org Blueprints instead of Schema.org Metatag, it's far more flexible in how it works.

I'm moving this to the 2.0.x branch, no further work is being done on the 8.x-1.x branch.

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

ptmkenny’s picture

Added a merge request with the code from patch #44 to make it easier to track future work.