-
Notifications
You must be signed in to change notification settings - Fork 12k
Is there a way to conditionally include scripts in index.html as in analytics? #4451
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
Comments
Thanks @Ionaru I'll have a look. |
Hi I have the same question. The problem I have is when doing ng build the script code in the index is not included. Any updates? |
Be sure to put the script code outside the |
thanks @Ionaru including the tag in the HEAD is working for me. |
The initial question has not really been answered here, I'm also wondering how that could be solved. Consider if you add f.e. Google Tag Manager or Google Analytics integration to your site, and you have different workspaces (or properties in GA) setup for your different environments. The appropriate script&noscript tags area added to the Best case scenario would of course be if Until there is support for that, what would be a decent workaround? I guess checking environment variables on server side and serve two different index.html files would be one option. Am using a simple static files server currently though so curious to whether there is some more elegant way of solving this as part of the build process instead |
You could try adding some code to add different Analytics properties when running in different environments. Like this: import { environment } from './environments/environment';
if (environment.production) {
document.write('<script type="text/javascript">// ProductionAnalyticsCodeHere</script>');
} else if (environment.staging) {
document.write('<script type="text/javascript">// StagingAnalyticsCodeHere</script>');
} If you do this in main.ts, then the code gets added to the webpage as early as possible. It is also possible to put |
The CLI doesn't provide any such functionality, no. This was requested in #4288. In past projects what I did was having Angular services that correctly run these scripts, and use the correct analytics token provided inside the environment files. @Ionaru has provided some pretty good solutions though, cheers! |
Wont this fail tests? (using document?) |
@filipesilva I don't think it's a 'pretty good solution', it's mostly a workaround which fortunately works fine |
@Ionaru solution is the best workaround I found so far. main.tsimport { enableProdMode } from '@angular/core';
import { env } from './environments/environment';
if (env.production) {
// add Google Analytics script to <head>
const script = document.createElement('script');
script.innerHTML = `(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','GTM-XXXXXXX');`;
document.head.appendChild(script);
// disable Angular development mode
enableProdMode();
} There is a "but" to this workaroundAdding the So be ready to throw away non javascript users tracking if you want to use that workaround OR you could keep the index.html<body>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-XXXXXXX"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
...
</body> |
Solution provided here will not work in Angular Universal, due to direct access to the So in the AppComponent: import { DOCUMENT } from '@angular/common';
...
public constructor(
@Inject(DOCUMENT) private doc: any
) { Then I used a private method called on private setGTagManager() {
const s = this.doc.createElement('script');
s.type = 'text/javascript';
s.innerHTML = '(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\',\'' + environment.tagManagerId + '\');';
const head = this.doc.getElementsByTagName('head')[0];
head.appendChild(s);
} As you can see I imported the tagManager ID from the global Also if you use Angular Universal be sure to run this code only on the server, or it will import the script twice in the browser. Hope this helps. |
For analytics you can use multiple index.html pages (like index.prod.html, etc) and fileReplacements (https://github.com/angular/angular-cli/wiki/stories-application-environments). |
@pbazurin-softheme how to change between different index.html files with configurations, any example or snippets? I tried with changing "options" but it didnt worked. |
{
...
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
},
{
"replace": "src/index.html",
"with": "src/index.prod.html"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true
},
"staging": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.staging.ts"
},
{
"replace": "src/index.html",
"with": "src/index.staging.html"
}
],
...
} @ramk-bharathi This is my |
@pbazurin-softheme it seems like your snippet would work for my needs (adding tags instead of <script> tags) but it doesn't. Are you certain that it works for you? If not, maybe the index.html in /src is handled differently in Angular CLI vs other files. Currently I have to use pre and post hooks with my npm package scripts in order to swap out the correct index.html. |
@meetai ahh. Yes. My comment was specific to cli 6.0.8. Apprciate the clarification. |
This client side package should also address the original question outside the context of the Angular CLI: https://github.com/anywhichway/scriptswitch. |
@lonaru solution worked for me also. Thanks! |
@pbazurin-softheme Your solution is the most stable one. It prevents adding script tags at runtime (which would nullify the |
Please edit this to point to the much better answer at #4451 (comment) |
This issue has been automatically locked due to inactivity. Read more about our automatic conversation locking policy. This action has been performed automatically by a bot. |
No description provided.
The text was updated successfully, but these errors were encountered: