Display an HTML page in a custom widget, with the specific page URL designated in a column

I have been trying to modify the image viewer example (grist-widget/viewer at master · gristlabs/grist-widget · GitHub) to show a web page (in an iframe) in the custom widget, based on what row is selected in another widget.

Right now I’m getting a broken image.

I’m just beginning to learn how to do simple coding, but I’m thinking this may have to do with the code being written to display an image file on an HTML page (the widget) rather than it being meant to embed a whole page. Can you help me modify the code so that this will work?

Thanks in advance

For embedding an HTML page, try using the renderhtml custom widget, available at this URL: https://gristlabs.github.io/grist-widget/renderhtml.

There is an example here: https://public.getgrist.com/f95AzwmFZSp3/Embedded-Twitter-Widget/m/fork. To use it, make a single column visible to the widget, containing the URL of an HTML page.

The widget supports some parameters for what tags to enable in the iframe; the example above includes ?tags=script in the URL because that’s necessary to embed from Twitter. But for simple examples, it shouldn’t be needed.

By the way, for anyone looking for an example of using the image-viewer widget, there is an example here: https://public.getgrist.com/uMphMkdP6BZQ/Linked-Images/m/fork.

1 Like

Thanks so much @dmitry-grist

It seems to be working now, but intermittently. When I immediately go to the page, the widget shows the HTML (in this case, LinkedIn Profile badges), but when I then try to select another record in the linked table, it doesn’t load – the widget remains blank.

Any tips on how to solve this? Is there some setting that requires the widget to be refreshed? I’ve got the custom widget linked to get data from the same table I’m using to select the record/row – other widgets change properly when I select a new row, but not the custom widget to render HTML.

Thanks for your help!

Hi @Pamela_Parker! Hmm, it looks like there are several possible culprits, but the ultimate issue may be specific to LinkedIn.

Firstly, there is the question of what HTML is rendered. I went ahead and added a “LinkedIn Badge” example to https://public.getgrist.com/f95AzwmFZSp3/Embedded-Twitter-Widget/p/3/m/fork. I found it important to include the script portion below the <div> in the HTML. It’s also important to tack on ?tags=script to the URL of the Custom Widget.

With this, some profiles sometimes loaded. In fact, initially they loaded very well. But soon stopped. On the browser’s debugging console, I see requests to LinkedIn failing with error code 999:

That’s not a normal code. Google brings up as first answer that it means “LinkedIn does not like you”. This discussion is a bit more revealing: https://www.reddit.com/r/linkedin/comments/ixwoxr/999_request_failed_with_reason_codes_1_2_1/ – it sounds like LinkedIn considers a series of badge requests as suspicious (sounds like there are profile-boosting tools with a similar behavior, which it’s trying to block). It is probably blocking the IP address from requesting more profiles once it identifies the requests as suspicious.

Other reasons the page might not load is if you have strict privacy settings in the browser (since LinkedIn is a known tracker across the web, requests to it may get blocked by more privacy-oriented browsers).

The profile badges don’t seem to work for company pages at all, so that’s another reason it may show up blank.

But after fixing all other reasons, if you open the network tab of the developer console in the browser, and find 999 error codes, it means the requests are getting blocked by LinkedIn, and am not sure if there is a workaround.

Ok, that makes sense. Thank you. Possibly stupid question, but where do I see the debugging console?

I might try to get a developer account with LinkedIn and see if I can do something that way. If they offer free accounts, that is.

Really appreciate this, BTW, and it boosts the utility of Grist for me immensely.

Oh, the last link I shared had instructions for opening the browser’s developer console (which I referred to also as debugging console): Finding Your Browser's Developer Console | Balsamiq. Instructions are a bit different for different browsers, but all have a “Console” tab that shows messages including warnings and errors, and a “Network” tab which shows network requests with response codes.

Thanks. I was aware of that but didn’t know if the Custom Widget or Grist had a log or debugging console itself. I’ll look at the browser info going forward. Again, appreciate it much!

Ok, I’m still trying to make this work, but with a different page – not LinkedIn. It’s actually a script to display an RSS feed, so there shouldn’t be any limitations on fetching it. I’ve tried both JavaScript and iframe, and I am getting errors. Specifically, it looks like it has to do with a line I copied from your renderhtml widget example:

I’m pasting the error log here. Am I still doing something wrong or is there something on your end going on?

P.S. I embedded the same code on my own WordPress site and it worked fine. iFrame on top and JavaScript on the bottom: Test Page - Pamela Parker

is renderhtml the old version of the current HTML Custom Widget?

I can´t get it to work

“HTML Custom Widget” has the identifier renderhtml, so it’s the same one.

It sanitizes (i.e. blocks/removes) certain tags by default, including iframe. To enable more tags, no one has created a friendly way, so the only way supported today is to switch to using “Custom URL”, and place there the URL of the underlying widget with extra parameters. Specifically, to enable iframes, try “Custom URL” with this URL:

https://gristlabs.github.io/grist-widget/renderhtml?tags=iframe

To enable other tags, add them as a comma-separated list, e.g. ?tags=script,iframe.

1 Like

interesting. Would it be possible to NOT sanitize iframes from the same Grist installation?

Or maybe have the plugin have some checkboxes that do the same as the tags?

showing other Grist documents in iframes (as embed or singlepage) is a great way to mix different documents in one (you can´t relate them, but you can for example have KPIs in one document and Non Conformities Register in another document, and if a KPI presents a non conformity you can create a Non Conformity in the iframe showing the other document.

Just one example.

I will try your method above.

I was unable to display another Grist document in the iframe even after using the custom URL with the tag

I wonder if the problem is that the Custom Widget is outside of my network, which can´t be accessed from outside. Grist is accessing something in Github which is trying to access something in my “island” network.

Maybe if I put that renderhtml widget in my own network, it will work

Could you check if there are errors in the browser console (in the console log or the network tab)?

Ah yes, it’s browsers being careful. It looks like you are serving Grist on an internal network without SSL (HTTPS). The custom widget is served via HTTPS, and browser don’t like loading insecure iframes from inside secure ones.

Of course, the better advice is to serve Grist over SSL, even on a local network. But the alternative would be to serve the renderhtml code locally on your network without SSL (the code is in GitHub - gristlabs/grist-widget: A repository of custom widgets to embed in Grist documents)

maybe I should do BOTH. Have the plugin in our local repository and serve it, as well as put Grist with an SSL.

It also didn´t work directly inside Grist’s servers.

I used te URL widget, inserted Render sanitized HTML from a cell in the WIdget Custom URL

However, first time, it asks for login (despite user already being logged to Grist)

and when I tried to login using Google, Google refused the connection

It looks like you at least solved the HTML Viewer widget issue: the error is now completely different from before. It looks like the widget rendered this time: instead of blank, it’s actually running the widget code and rendering the HTML in the cell, yes?

The issue now is that the HTML in the page isn’t doing what you expect.

It’s trying to render another Grist doc inside an iframe.

This won’t work when the docs are on different domains: in a cross-origin embedding of Grist, cookies will not be sent. This is an important protection measure against a certain range of attacks (you can learn more about it, for example, here).

This means that logging in within that iframe wouldn’t work even if Google allowed it. Google doesn’t allow it (for similar reason as Grist). For me, Firefox shows a clearer error about Google: “To protect your security, accounts.google.com will not allow Firefox to display the page if another site has embedded it. To see this page, you need to open it in a new window.”

You should be able to embed Grist documents that are publicly viewable. But for documents that need a login, you can only embed them from the same origin.

Yeah, I was able to make it work with some Grist docs. Created a thread at Discord about it.