Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Google analytics Support for the Gradio Application Hosted on HF Space #5954

Closed
ravishk007 opened this issue Oct 17, 2023 · 15 comments
Closed
Labels
enhancement New feature or request

Comments

@ravishk007
Copy link

Is there any way to integrate our own Google Analytics HTML tags with the application developed via Gradio and hosted on HuggingFace Spaces?

@ravishk007 ravishk007 changed the title Google analytics Support for the Gradio Application Google analytics Support for the Gradio Application Hosted on HF Space Oct 17, 2023
@abidlabs
Copy link
Member

Not at the moment, but we'll look into this @ravishk007!

@abidlabs abidlabs added the enhancement New feature or request label Oct 17, 2023
@abidlabs
Copy link
Member

Hi @ravishk007 this should now be possible in Gradio 4.0. In Gradio 4.0, you can set the head parameter in Blocks that lets you include arbitrary JavaScript or other tags in the <𝚑𝚎𝚊𝚍> section of your Gradio app!

E.g.

ga_script = """
<script async src="https://www.googletagmanager.com/gtag/js?id=G-DNJN1PF3CS"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
gtag('js', new Date());

gtag('config', 'G-XXXXXXX');
</script>
"""

with gr.Blocks(head=ga_script):
  ...

@jonathanasdf
Copy link

Hi, it looks like this approach doesn't actually work, checking with https://tagassistant.google.com/. It detects the tags shipped with gradio but not the one added with head=.

image

@abidlabs
Copy link
Member

Hi @jonathanasdf can you inspect the source of the page yourself? Is the script being added as expected?

I'm wondering if the issue is that Hugging Face Spaces runs Gradio apps inside of an iframe and perhaps Google Analytics doesn't work inside of iframes.

@jonathanasdf
Copy link

Ah this was something I started with demo.launch(share=True) not something on spaces so that shouldn't be the issue.

Looking at the source and testing this a bit more, it seems like only the first script tag from the head is being applied

"""
head = """
<script>console.log('hello')</script>
<script>console.log('world')</script>
"""
with gr.Blocks(head=head):

image

Additionally, in this case it seems like the script tag is added to the head section after the page already loads, so it never gets executed? The console output is empty.

@abidlabs
Copy link
Member

Hmm super weird, but yeah I can reproduce -- @jonathanasdf would you be able to create a new issue with your findings regarding the head parameter? That will be better for visibility for our team and we can work on fixing this.

@jonathanasdf
Copy link

Here is a workaround specifically for google analytics

ga_script = """
<script async src="https://www.googletagmanager.com/gtag/js?id=G-XXXXXX"></script>
"""
ga_load = """
function() {
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'G-XXXXXXX');
}
"""

with gr.Blocks(head=ga_script) as demo:
  ...
  
  demo.load(None, js=ga_load)

@abidlabs
Copy link
Member

Thanks so much @jonathanasdf! We'll work on getting the underlying issue fixed as well (cc @dawoodkhan82)

@dwipper
Copy link

dwipper commented Dec 21, 2023

@abidlabs @jonathanasdf I got the standard approach working in 4.10.0. I'm looking to also implement Tag Manager. It requires script in the header:

<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','XXXXXXXXXXXXXXX');</script>
<!-- End Google Tag Manager -->

And script right after the body tag:

<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=XXXXXXXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->

Is this possible? i.e. is there a body param for blocks? i.e. "with gr.Blocks(body=gtm_script):"

@dawoodkhan82
Copy link
Collaborator

@dwipper So we don't have a body param for blocks. But can you try adding your Google Tag Manager (noscript) to a gr.HTML() component. gr.HTML() technically does add html to the body of the app, but it's nested within a bunch of other divs. Let me know if this approach works.

@dwipper
Copy link

dwipper commented Dec 21, 2023

@dawoodkhan82 I assigned this to a gr.HTML component in my UI:

<!DOCTYPE html><html><head>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'[https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f)](https://www.googletagmanager.com/gtm.js?id=%27+i+dl;f.parentNode.insertBefore(j,f))f;
})(window,document,'script','dataLayer','XXXXXXXXXXXXX');</script>
<!-- End Google Tag Manager -->
</head>
<body>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=XXXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<span style="display: flex; justify-content: center;">
<iframe width='1075' height='500' style="border-radius: 10px;" src='https://www.youtube.com/embed/IhUZz32V-6Y' title='Episode 51 | Common Struggles in NIL Content Creation' frameborder='0' allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share' allowfullscreen></iframe>
</span></body></html>

When I tested the page with the Google Tag Manager, it said "tag not found". I have a feeling it may have to do with the multiple levels of iFrames that make up the Gradio page structure? I may try adding the head script to the Block head script in the app, and see if that helps. I'll still have to add the body noscript to the gr.HTML component value.

@dwipper
Copy link

dwipper commented Dec 21, 2023

@dawoodkhan82 Actually, looks like moving the head script to the Block header worked (at least the site test came back Ok.) Now I will need to try to implement an Element Id tag to see if the data actually flows through......

@dwipper
Copy link

dwipper commented Dec 22, 2023

@dawoodkhan82 Bingo! It worked with the header script in the head, and the body noscript iframe in the body of the gr.HTML component. While I can gather data about what is displayed in the gr.HTML component, next I'm going to see if I can access other Gradio components like gr.Textbox or gr.Dropdown......

@dwipper
Copy link

dwipper commented Dec 22, 2023

@dawoodkhan82 The good news is that if I add an elem_id to the Gradio component, I can access the component it in the Tag Manager, i.e. get the label of the component, but it doesn't find the actual value of the component. I'm not a DOM expert, but I don't see any representation of the actual value of the dropdown or textbox when I inspect the page, so it makes sense that the Tag Manager can't read the value. Any ideas?

@dawoodkhan82
Copy link
Collaborator

@dwipper Maybe you're reading the value before it's actually updated in the DOM?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants