This module automatically supports personalisation by means of tokens in newsletter nodes. For some sites/newsletters, that might not be needed so there should be a setting to disable it.

Reasons:

  1. Token replacing is bad for performance and cacheability. simplenews_node_view() causes every newsletter page to vary per user. In particular this affects a site where a main content type used to display "article/blog" also has newsletter enabled to allow sending out the blog by email.
  2. When editing a newsletter page, this module adds a 'Replacement patterns' section. This is baffling to a non-techy editor, and the developer might prefer not to show it.
  3. If a batch contains more than 20 authenticated users, you hit a "recursion" limit as described in #3081703: Add setting to disable per-user rendering . This is a core limitation: #2940605: Can only intentionally re-render an entity with references 20 times.

The default value of the new setting was changed to FALSE in #3248026: Problems with inserting tokens in newsletter fields.

Comments

AdamPS created an issue. See original summary.

adamps’s picture

Title: Per-newsletter setting to disable tokens » Per-newsletter setting to disable tokens/personalisation
Version: 8.x-1.x-dev » 8.x-2.x-dev
Issue summary: View changes
Related issues: +#3081703: Add setting to disable per-user rendering
promo-il’s picture

+1
I just disabled it in simplenews.module

if (\Drupal::moduleHandler()->moduleExists('token')) { RETURN;
      $form['simplenews_token_help'] = [
berdir’s picture

For the performance part, it could just manually call \Drupal\Core\Utility\Token::scan and only call token replace if there are any tokens. And note that this function isn't being used for sending newsletters, it excludes email view modes. This is specifically only for viewing newsletter nodes on the website.

berdir’s picture

or the performance part, it could just manually call \Drupal\Core\Utility\Token::scan and only call token replace if there are any tokens.

Actually, that already is done automatically, only generate() adds the cacheablity metadata and besides, it wouldn't add the current user context through that anyway, so in fact it looks like we might be missing cacheability metadata?

If you have troubles when sending mails then it is not related to this function, the send process has its own caching, which is pluggable, see \Drupal\simplenews\Mail\MailCacheBuild. That said, doing it through batch in the UI is special because those are POST requests which don't have render caching, but if you send newsletters to authenticated users then you could implement your own cache implementation that caches for authenticated users too.

berdir’s picture

The only thing that I agree is an issue (that this module could do something aboiut) is that the token browser shows up. Agreed that could either be a setting or also just a permission, kinda doubt it needs to be a per-newsletter thing then if performance isn't relevant.

adamps’s picture

Version: 8.x-2.x-dev » 3.x-dev

You are right: if there are no tokens then no metadata is added. However, the node edit page has a token replacement box which encourages a newsletter editor to enter tokens. If that might be a bad idea then we can add an admin setting allowing the site owner to disable it.

it wouldn't add the current user context through that anyway, so in fact it looks like we might be missing cacheability metadata?

The token data is missing user, but contains subscriber, which seems reasonable. When viewing the page that uses tokens for a second authenticated user then the subscriber is different so presumably it triggers a cache miss in the page cache. It could however be a cache hit in the render cache for the node (unless the node itself varies per user).

if you send newsletters to authenticated users then you could implement your own cache implementation that caches for authenticated users too.

Presumably 1000s of sites send newsletters to authenticated users - we can hardly claim that this is an unusual choice requiring custom code. If performance is unacceptable sending to authenticated users then I would count it as a bug. However I would expect render caching of the node is solving the problem - or is that disabled from cron also?

And note that this function isn't being used for sending newsletters, it excludes email view modes.

Yes but there is exactly the same code for sending newsletters in MailEntity::getBodyWithFormat(). The setting would control both places.

The same setting could also disable the user switching. The use case for this seems fairly rare (presumably to display some extra 'restricted access' information in the newsletter to authenticated subscribers, maybe with field_permission module or similar?) and it seems to be contributing to the bugs and performance degradation.

If we make the change in a new major release then we can even default the setting to off. So I'm tempted to add this in soon before a 3.x beta.

@Berdir - any more thoughts/advice very welcome.

adamps’s picture

Ah of course we can't disable the token replace in getBodyWithFormat() because it replaces the footer tokens such as unsubscribe. Potentially user switching is best kept separate too. So that would leave something like this.

Global newsletter setting: "Show token browser (discouraged)", defaults to FALSE. Description = "Show token browser on the node edit page. Note that in many cases, visitors will see un-replaced token codes when browsing content". Effect of setting when false: remove the token browser, and disable the code in simplenews_node_view().

Some example cases where it doesn't work are:

  • Anonymous users
  • Unsubscribed users
  • Viewing nodes in any way other then their own page: teasers, views, etc.
  • Fields that don't render to produce '#markup'
  • The [newsletter:*] tokens are not replaced (could easily be fixed)

In fact I'm not sure if I can find a case where it works!!

adamps’s picture

The documentation for hook_ENTITY_TYPE_view() says that it is called before rendering, so maybe that is why it cannot find a #markup element?

adamps’s picture

Title: Per-newsletter setting to disable tokens/personalisation » Setting to show token browser
Status: Active » Needs review
StatusFileSize
new5.64 KB

OK, I fixed simplenews_node_view(), now working except obviously not for the case where there is no subscriber.

adamps’s picture

Issue tags: +Plan to commit
berdir’s picture

Fine as long as it stays an option, but FWIW, tokens/personalization in newsletter is a very common feature so I don't think that this feature should be off by default. A lot of users might not even know that it exists then. Of course it depends on which tokens you use and what kind of content it is and how it's displayed. You can also instruct the token API to remove placeholders, but it depends on how tokens are used whether that is an improvement or not.

Instead of a setting, we could also hide it behind a permission. Can't hide it for admins then though.

For sending newsletters, tokens are specifically designed to improve performance, as token replacement happens on the rendered newsletter. That's it's broken for most formatters in D8 is not that surprising, we never really used that part I think.

Also, the simplenews subscriber tokens for example specifically support the view-online link that provides the subscriber info in the query.-

Last thing, careful with anonymous functions in render arrays, of they are serialized for any reason then this will explode. Less common in regular render arrays, but you can never be certain, definitely breaks forms for example.

adamps’s picture

Thanks Berdir. I agree with you on almost all. I chose the setting rather than permission so it can work for admins.

I debated whether to remove the placeholders, but I saw a potential problem - if a node with newsletter function contains any text that resembles a token then it would get removed. Not especially likely but it could happen - perhaps on a Drupal related site. I could be persuaded to change on this one.

Also, the simplenews subscriber tokens for example specifically support the view-online link that provides the subscriber info in the query.-

I'm not familiar with that token - does it require an extra module? It sounds like something you would put it in the footer part of the template rather than in the node. NB This setting only disables tokens in the newsletter entity - not those in the template.

For sending newsletters, tokens are specifically designed to improve performance, as token replacement happens on the rendered newsletter. That's it's broken for most formatters in D8 is not that surprising, we never really used that part I think.

The tokens work very well for sending newsletters in terms of performance, and being bug-free. The problems I found/fixed were when viewing the node as a webpage. Previously the code was apparently totally broken and it's hard to see how it could have worked in D8.

So that leaves the question of what should be the default setting? The reason I left it disabled is because it seems to break many very common sites such as blogs - anyone reading down the blog would see token codes. If we enable it by default, do you have any ideas what to do about that? Maybe we could pass in a dummy subscriber object??? It could easily crash though😃.

berdir’s picture

> I'm not familiar with that token - does it require an extra module? It sounds like something you would put it in the footer part of the template rather than in the node.

Yeah, sorry. I think that was something we worked on a for a D7 project as a patch/issue but never managed to make it an official feature of the module. IIRC it wasn't even for tokens then but other custom personalization.

Has been a while ago since I did anything with simplenews, which is one reason why I've been so absent in the issue queue.

> Previously the code was apparently totally broken and it's hard to see how it could have worked in D8.

Yeah, keep in mind that we've been porting the module during D8 alpha and things still changed quite a bit between alpha and stable 8.0, so it might have worked as we ported it, but not in a very long time.

> NB This setting only disables tokens in the newsletter entity - not those in the template.
> So that leaves the question of what should be the default setting? The reason I left it disabled is because it seems to break many very common sites such as blogs

Got that. I do wonder if that's really necessary to not replace the tokens and if it is not sufficient to just not tell editors that they can use tokens. As we discussed, if there are no tokens, then it's just a single regex and it will return it basically immediately and it shouldn't affect caching. So it might be sufficient to just control the UI? no strong opinions on that though. At least the setting name and description only talks about the browser, so that should IMHO be clearer that tokens will not be replaced at all then in node view?

And maybe the token explanation on the node form itself could be extend with the node that depending on the used tokens, it will not work then?

Same on the default value. Showing it by default would IMHO make sense, to kind of show off what the module can do, but I'm also OK if we don't. That said, I would suggest to make the update function so that it keeps the current behavior, so at least that I would set to TRUE. So if they did use it, it doesn't suddenly stop to work.

adamps’s picture

OK I have change the default to TRUE, with some fallback of a dummy subscriber object.

Status: Needs review » Needs work

The last submitted patch, 15: simplenews.token-browser.3038794-14.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

adamps’s picture

Status: Needs work » Needs review
StatusFileSize
new6.84 KB
new1.1 KB

Thanks @Berdir. I feel it's good to make the option so it disables the token replacing also: firstly in case it breaks something people have a solution; secondly, it enforces a site policy in case the editor gets smart and types in a token code even without the browser. So I altered the description as you suggested. The default is on now (both for new sites and upgrades), which feels OK to me now that the code leaves raw token codes behind much less often.

And maybe the token explanation on the node form itself could be extend with the node that depending on the used tokens, it will not work then?

Beg pardon I don't understand that one.

Status: Needs review » Needs work

The last submitted patch, 17: simplenews.token-browser.3038794-17.patch, failed testing. View results
- codesniffer_fixes.patch Interdiff of automated coding standards fixes only.

adamps’s picture

Status: Needs work » Needs review

Just a random fail

adamps’s picture

I raised #3248026: Problems with inserting tokens in newsletter fields to describe the remaining problems with this feature. I updated the setting description.

adamps’s picture

Fix the config setting name and description to match current behaviour

adamps’s picture

Title: Setting to show token browser » Setting to enable token replacement in newsletter issue fields
adamps’s picture

Status: Needs review » Fixed
Issue tags: -Plan to commit

  • AdamPS committed 73797c8 on 3.x
    Issue #3038794 by AdamPS: Setting to enable token replacement in...
adamps’s picture

Issue summary: View changes

Status: Fixed » Closed (fixed)

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

ressa’s picture

Adding Token support was great, and it works well -- thanks!

However, it looks like Token support is enabled by default, whether or not you enable it under Simplenews > Newsletter - /admin/config/services/simplenews/settings/newsletter:

Customization

[ ] Newsletter tokens (caution)
Enable tokens in newsletter issue fields. Show a token browser on the node edit page and replace tokens when viewing a node (which may reduce performance). [...]

If Tokens are always enabled, perhaps the text could be updated to this?

[ ] Enable token browser (caution)
Enables token browser in newsletter issue fields. [...]