Dynamically <head> tags

Is there any possibility to dynamically set and remove tags of the document? I need this to integrate the Facebook Like Button. Facebook specifies the content of the page over meta tags: http://developers.facebook.com/docs/opengraph/

e.g.

The Rock (1996) ...

Well, I already have my own AbstractApplicationServlet subclassed, this helps me to define the noscript tag and so forth, but now I should change the meta tags in the dynamically, as every page represent different content. Thank you for your help, Vaadin is great!

My impression is that it is not possible. I understood that the Open Graph Protocol reads the page with HTTP to get the metadata, so changing it with AJAX can’t work. Well, if the metadata is read later by some OGP’s JS code, then changing it in the DOM with either JavaScript or in a GWT widget might work.

See for example
this article
.

Well, it might be possible with some trick. For example, you could put the Facebook Like button in an Embedded (iframe), which is connected to a StreamResource or URIHandler that outputs the HTML page for it. It would need to have a redirect to the actual Vaadin application using the correct URI fragment. Well, the redirect should not work when the page is shown embedded in the Vaadin app…I hope that is possible somehow. Or does Facebook follow redirects to get the metadata? In that case it might not work that way.

Thank you for your reply, I already guessed that it will be a little tricky. Actually, Facebook limits itself to cooperate only with non ajax applications using this technique which wonders me. Maybe I’ll find another Facebook JS library which could solve this problem and if not I need to use the AddThis plugin, which is not bad, but certainly not that ease eye catcher as the Like-Button.

In your linked Article, it is recommended not to use an # in the url to specify a content path. Well, Vaadin works like that and certainly Google has its own mechanism for crawling ajax content. What do you think about using # in urls to specify content?

Yes, the # (URI fragment) handling in Ajax apps does not work crawlers that want to read HTML. Google has a special handling for #! paths, but apprently Facebook doesn’t.

So, there are two basic ways to specify content:

  1. Use URL path such as /myapp/some/path/to/content/xyz. This works for crawlers and you can return the special metadata headers in a servlet. This doesn’t work with Ajax (such as Vaadin), because the URL path stays always the same.

  2. Use URI fragment path such as /myapp#some-path/to-content.xyz. This doesn’t work with crawlers, unless especially supported, such as Google #! notation, which also requires a HTML page that can be accessed by a regular URL.

You could try the Embedded/iframe trick to combine the two methods by embedding a dynamic HTML page in an iframe inside a Vaadin application. The Facebook button would be in the embedded page. I don’t know for sure if it would work, but possibly.

Sorry to bother, but can you confirm that this worked?

Thanks,
Yuri.

Is it it possible to get the fragment part when servletInitialized() gets called? So from the first request when the page gets accessed first?
Or is there a better way to set/change meta-tags nowadays, since the topic is already 6 years old?

Still no answer? Or is it because this thread found a downside of vaadin that I get no answer?

Hi,
in vaadin 7 you can register a BootstrapListener to modify the html content

[code]
class MyServlet extends VaadinServlet {
@Override
protected void servletInitialized() throws ServletException {
getService().addSessionInitListener(event → event.getSession().addBootstrapListener(
new BootstrapListener() {
@Override
public void modifyBootstrapFragment(BootstrapFragmentResponse response) {

                }

                @Override
                public void modifyBootstrapPage(BootstrapPageResponse response) {
                    Element head = response.getDocument().getElementsByTag("head").get(0);
                    Element meta = response.getDocument().createElement("meta");
                    meta.attr("name", "name");
                    meta.attr("content", "content");
                    head.appendChild(meta);
                }
            }
        ));
    }
}

[/code]See also
here
for more information

HTH
Marco

I know that. But thats not very dynamic. It does not matter which page gets called, the output will always be the same. To me thats a big limitation.

Sorry, I have not understood your question.
By “page” what do you mean? Different UI classes? Or while navigating from a view to another in the same UI?

Can you elaborate a bit your needs?

I have only one UI class. I would like to add dynamic Metatags depending on which fragment gets accessed. It doesnt really matter while navigating in the UI, but it does matter while first accessing the UI with different fragments.

For example if I run the app locally I could either put localhost:8080/#!login or localhost:8080/#!show/id to open the same UI in the browser. Depending on that fragment I want to add different meta tags to the client. It might even depend on the id after #!show. After the inital request it doesnt really matter if the user navigates within the UI.
Those meta tags could be needed for fb for example.

Is this possible to do with vaadin?


In BootstrapPageResponse you have access to VaadinRequest (so in many cases you can access also HttpServletRequest);
you can then extract the fragment from requestURI and handle it as you want.
This will be computed only on the first request, when the html page is composed and sent to the client.


May this approach work for you?

EDIT
Sorry, forgot that the above suggestion will not work for fragments

EDIT 2:

A solution could be a client extension for UI; in then connector, on first state change, you add meta tags.

The server side extension gets the fragment from ui.getPage().getFragment() and then adds metatag objects to
the shared state.
The connector collects meta tag objects from shared state and adds them to the head element of the document.

I can try to create a sample project if this can be of helpful.

EDIT 3:
This will not work with crawlers that does not support javascript

Yea I had checked the BootstrapPageResponse in a debugger to see if it contains the fragment somewhere. Sadly I couldnt find it there.

The javascript solution would work for google, but not facebook. My goal was to show some info about the linked page if posted on facebook. I really appreciate you talking your time to help me. Do you have any other ideas?

Did you take a look at
Volga addon
? (I’m pretty sure you already did it :slight_smile: )

Used with
History addon
your SPA will have URLs like http://ocalhost:8080/show/id (instead of using fragments) so they can be parsed at server side.

If it does not fill your requirments it can always be a good starting point.
If this don’t work for you I’ve no further ideas :slight_smile:

HTH
Marco

Those look really great! I didnt know about them, but I will try it out for sure. The history addon seems to solve my problem and with the volga addon my code probably gets easier.

Thanks a lot already! This will probably work :slight_smile: