When using this module and something like paragraphs, there is an annoying side-effect when the check-response is a bit slower:
* Add a new paragraph, an automatic check is performed
* Type in some data in the paragraph title field
* Press the 'add paragraph'-button, and an automatic check is performed again
* Press the 'add paragraph'-button again *before* (a couple of times) the last check is finished
* Now one of those new paragraphs is gone
I think it's because of the form-submit that is done during the automatic check. When the check is done, the form-html is replaced with the response and you end up with the replaced form where one (or more) of the newly added paragraphs was not present yet.
I've made a patch that adds a 'manual check'-option to the field (in form widget)
See also the comment here: https://www.drupal.org/project/yoast_seo/issues/2974301#comment-12843185
Issue fork yoast_seo-3067487
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
Comment #2
spadxiii commentedComment #3
aaron.ferris commentedThanks for this, seems to work well from my initial testing and is badly needed for content types that are heavy on the paragraph side.
A potential nice to have would be to have a global option rather than per field.
Noticing the following on node view after create/add
I think we're missing Schema changes in the patch
Comment #4
aaron.ferris commentedComment #5
aaron.ferris commentedThis perhaps needs more thought, the above notice is firing because 'edit_manual_checking' forms part of the element itself, as opposed to a value hence being an undefined index. I am attaching a patch that seems to work in my implementation.
Comment #6
spadxiii commentedI noticed a little bug where pressing the preview-button again would not update the results. This was caused by this patch removing the onchange-handlers. I re-enabled these handlers and moved the manual-check into the refreshData method.
Good find on the notice; I didn't notice that one.
I added my change to the patch in #5 as that has the notice-fix which seems to work.
Comment #7
stefan.kornOn initial load of the entity no analysis is performed and the SEO status is therefore not correctly shown. You can correct this by pushing the button, but it is irritating that the status quo is not correctly displayed. For example you see the status "Good" in the content overview and then while editing the content the status is shown as "Bad" (until the button is pressed). So I would propose to have an initial analysis automatically.
This patch should help with this. It is also taking care that the inital analysis is not performed for new content, because it makes no sense there.
Comment #8
stefan.kornComment #9
mpp commentedLooks good, thanks!
Use $this->t('Manual checking enabled')
Comment #10
tichris59 commentedThis features seems really great especially for paragraphs user and ajax problems we have, could you add it to the next release ?
Comment #13
svendecabooterAttached is an updated patch with the fix suggested by mpp.
I also tried creating an merge request with that new drupal.org feature: https://git.drupalcode.org/project/yoast_seo/-/merge_requests/1
Not sure what the maintainers of this module prefer, so adding both :)
Comment #14
svendecabooterComment #15
mpp commentedWhohoo, we have merge requests! Aaand inline code suggestions, time to party!
+ if(!this.config.is_new) {
+ this.$form.find('.yoast-seo-preview-submit-button').mousedown();
+ }
=> is missing a space. Thanks @sven fot the update, I added an inline code suggestion for this.
Other than that this looks good, lgtm!
Comment #16
svendecabooterI tried applying the inline code suggestion in the MR, but that throws AJAX errors. Guess this feature is still too cutting edge right now :(
Comment #17
svendecabooterOK fixed the space now.. Not sure if you will get credit for that space or not @mpp :)
Comment #18
mpp commentedHehe, me neither. Thanks @sven, exciting :-)
Comment #19
mpp commentedMight still need some work:
Comment #20
kingdutchHi Sven and MPP,
Thanks for the proposed changes. There's a few things I would like to see if we can address, besides that I still think the automatic updating is a very useful feature, so if at all possible I would like to aim to preserve it.
Exploring an option with automatic updates
The core issue here stems from the usage of Drupal's AJAX API which does a psuedo form-submit and upon response updates the form. The form submit method is used because the form API does a lot of heavy lifting for us in terms of making entities available. Previously we would do that manually but this would cause a lot of issues.
This means that a form submit is needed. However, from what I understand of the issue, the problem is not necessarily that a form submit happens at all. The issue here is that the AJAX JavaScript subsystem will update the form when it gets a response.
There are two possible solutions that I see here. Either the logic on the server side is changed to change what the form processing sends back to the client. The alternative is to change the client side: either how the AJAX request is sent, or what happens to the response. I think changing the JavaScript code on the client is easiest.
The set-up of AJAX based on the
#ajaxcallback in the render property happens in the Render Element base class. The settings configured there are picked up in the ajax.es6.jsattachfunction.We can either change how we attach AJAX, doing it manually to allow our own set-up to be done client side. This allows us to mimick the submission while not using Drupal's default response handler which alters the page.
Alternatively we can monkeypatch the functions on
Drupal.AjaxCommands.prototypewhich receive the ajax request. The monkeypatched version can use the ajax object to figure out if this is a request for the Real-Time SEO module and filter out those commands, passing on anything else. The only command that will need to be preserved is the event trigger on the body element that contains the new analysis data.Either of these solutions should remove the side-effects that are currently associated with analysing an entity. This should help avoid clashes with any interactive events, not just paragraphs.
Feedback on the fix for manual updates
Although I'd like to explore the above options before merging anything, I have some feedback on the current proposed implementation.
1. The change in
js/yoast_seo.jsremoves the use ofrefreshData. While I do think the added is_new check is a good idea, I don't think we should bypass the check for other AJAX events thatrefreshDatadoes, so just wrapping that in the is_new check is probably better.2. I don't think the
this.config.manual_checkingshould happen in therefreshDatafunction. Instead we should use that configuration to decide whether or not to apply the event listeners at all.3. We should probably just use JavaScript to show the submit button on the form, by reading the config from the DrupalSettings. This avoids adding an arbitrary unsupported
#propertyto the form array. It also ensures that the button is only shown after everything has loaded and won't show when JavaScript is disabled (which is desired since the checking doesn't work without JavaScript anyway).Is it possible to write a test for the bug that's described in this issue? That would help us test out various scenarios and avoid regressions in the future.
Comment #21
kingdutchForgot to match the status to my comments.
Comment #22
kingdutchI've dug into this a bit deeper. It isn't actually caused by the Real-Time SEO module but it's a limitation of the paragraphs module.
The Real-Time SEO module provides two commands as a response to its update request. Those commands are
invoke-- which doesn't touch the form but just calls a callback -- andupdate_build_id-- which changes a value of theform_build_idinput, but doesn't otherwise alter fields in the form.To prevent doubt, I was able to filter out the
update_build_idusing a Proxy but even then the problem persisted.Finally I've removed the Real-Time SEO field altogether and am still able to reproduce the issue as follows:
InlineParagraphsWidget::addMoreSubmitadd asleep(10);to reliably simulate that adding paragraphs is slowThis is caused by the
insertcommand from the Paragraphs module sending the entire paragraphs field to the server and returning it as code to be replaced. This means your original input is captured in the paragraphs request and then enforced after. This is not caused by the Real-Time SEO module, since it's field isn't present.With that in mind I'm marking this as "Postponed (maintainer needs more info)" but unless someone can point to what exactly in the Real-Time SEO module is causing this (rather than an issue in Paragraphs), I'm leaning towards closing this as "won't fix".
The following issues for Paragraphs also provide some more background information on the general performance issue in Paragraphs and further demonstrate this is not Real-Time SEO specific:
The following Drupal core issue would stop the above scenario from being allowed in Paragraphs #2830295: Concurrent ajax submits cause user data loss.
------------
if anyone is interested, below is the code to show what commands are being executed. This was added for debugging in
Drupal.behaviors.yoast_seo.attachComment #23
svendecabooterThanks for the elaborate investigation Kingdutch!
However the site we experienced this issue with, does not use the Paragraphs module at all.
The content type where this error occurs is fairly simple, with just a few texfields.
The only thing that uses AJAX is the Media image field, which loads the media gallery.
If this is not a yoast_seo related issue, then it would be a Drupal core issue, given the above scenario?
Unless we have another module installed that intervenes here unknowingly.
Comment #24
svendecabooterUpdate:
When using the alpha5 release on my site, this issue seems to have disappeared.
Will investigate further if this actually solved things or not.
Comment #25
spadxiii commentedThe above commits were a rebase on 8.x-2.x so the mr can apply again
Comment #26
fernly commentedWhen loading a node edit page with the yoast seo field on it, then filling in a focus keyword and click outside that field (blur), it only shows the site URL with "undefined" appended to it. E.g.
https://www.mywebsite.comundefined. Clearly something goes wrong in the JS.I think when using the manual button, the blur functionality on the focus keyword field can be removed?
Clicking the SEO preview button again shows the example and analysis. Clicking the SEO preview button after page load without entering a keyword also generates the example + analysis.
Not sure if it's related but this started happening around the time we switched to the Gin admin theme.Probably not.Comment #27
kkalaskar commentedRerolled patch for 8.x-2.0-alpha9
Comment #28
fernly commentedCreated patch from current MR and updated it so the form change listener is not initiated when manual checking is enabled. This way the change on the "focus keyword" is ignored. See comment #26. Feel free to add this to the MR.
Comment #29
rbalajib commentedThis is not working with 2.1.0
Comment #30
rbalajib commentedComment #31
kingdutchI'm closing this as outdated. There have been a few changes to the module since this issue was opened.
Using the view mode configuration you can now decide exactly which fields are being included in the analysis. Additionally as part of #3008802: The page freezes while the Real-Time SEO module runs script, there is now a button that allows you to manually decide when to trigger an analysis.
Those two things should cover the scope of this issue. If that's not the case, please open a new issue.