Closed AnnMarieW closed 2 years ago
This would make Dash more powerful in terms of SEO.
+1
So here's one potential solution. Does this make sense? Is there a better way?
This is how to register a page with path variables in the pages/
folder. Note that the layout is in this file:
pages.path_variables.py
import dash
dash.register_page(
__name__,
path_template="/news/<section>/<topic>",
title="Plotly Times - World News" ,
description="The Plotly Times. All the data that's fit to plot. World news topic 1",
path="/news/world/1"
)
def layout(section=None, topic=None, **other_unknown_query_strings):
return dash.html.Div(
f"variables from pathname: section: {section} topic: {topic}"
)
You can create additional paths, with a different title, description and image that points to the layout above. They are added to the dash.page_registry
dict like this:
util.py
import dash
def register_paths():
dash.register_page(
"path_variables_path1",
path_template="/news/<section>/<topic>",
title="Plotly Times - Sports",
description="The Plotly Times. All the data that's fit to plot. Sports news topic 1",
path="/news/sports/1",
layout=dash.page_registry["pages.path_variables"]["layout"],
)
dash.register_page(
"path_variables_path2",
path_template="/news/<section>/<topic>",
title="Plotly Times - Sports",
description="The Plotly Times. All the data that's fit to plot. Sports news topic 2",
path="/news/sports/2",
layout=dash.page_registry["pages.path_variables"]["layout"],
)
The function above is called from the main app.py
. It's necessary to do it this way because the function must be called after all the layouts have been registered.
It works! Topic 2
Here's Topic 1
Just need to removed these two lines from the _path_to_page
function
The above is not a great solution for more dynamic pages as mentioned on the forum - Thanks @raptorbrad for your feedback:
I supposed that solution does work, but I don’t think it’s ideal for more dynamic page. I’m not fully aware of how the meta tags work, but a solution I thought of is either:
I’m not sure if either of these are feasible, since I’m not too familiar with what’s going on under the hood.
I have no idea if the following solution will work. I have not tested it, but I at least theorized what it could be. I don't know how search engines/the sharing piece of meta tags work, so this theory might be valid. I would be afraid that this doesn't work as it requires the page loading.
I'm not sure if I'll get to playing around with this, but I think we could maybe inject the meta tag into the head using Javascript. If how I traced the correctly works out, we could do the following:
We return additional meta information here and merge it with the _ID_STORE
data:
https://github.com/plotly/dash-labs/blob/275745c817f5f2d9bddb4203d06e12e1362d96d4/dash_labs/plugins/pages.py#L353-L358
Then when that data changes, we have a clientside callback that injects the new metadata into the headers. We could use the already existing clientside_callback located below or we can create another one. https://github.com/plotly/dash-labs/blob/275745c817f5f2d9bddb4203d06e12e1362d96d4/dash_labs/plugins/pages.py#L384-L392
I found this StackOverflow post that covers how to inject the meta data.
Any thoughts? Does this type of approach even work?
@bradley-erickson Thanks for your comments and feedback. Yes, I think an approach like this could work if it's necessary to update the meta tags during in-app navigation. However, it's probably more important to update the meta-tags when a link to the page is shared like how it's done here.
I think the bigger question is how (rather than when) to update the meta tags when there are variables in the path. Currently there is only one set of metadata per page in the dash.page_registry
. What's the best way to extend this so that the meta data can be a function of the path?
Perhaps we could use a dcc.Store
component as you suggested, but it should probably be a separate component so it's independent of how pages/
uses _ID_STORE
internally. This could be updated in a callback in the app so it's dynamic.
This dcc.Store
could store a dict similar to dash.page_registry
however the keys would be the path and it would only contain the meta data info. Any data here would override the current meta data info as generated in the _path_to_page function.
Well, that's what I have so far, I'm still open to other suggestions.
Here's another potential solution as suggested by @ chriddyp:
Allow the user to supply a function to dash.register_page
for the title and description. For example
dash.register_page(
path='/flowers/<flower_id>',
title=lambda flower_id: return get_flower_title(flower_id)
We’ll probably need to have some kind of check for the URL with flask.request.path within our function that creates the index HTML
Done - PR coming soon. Here's a preview: https://dashlabs.pythonanywhere.com/asset/inventory/department/branch-2000
As requested on the forum:
I would love to see this include customizing the meta data based on the path variables.
Example: We might have urls like /news/sports/1 and /news/sports/2. Each of these articles cover different topics and the article title and overview should be displayed when sharing instead of a generic text about sports articles.