I need something to detect changes on the url but the page doesn't do post back, it changes dynamically adding just the div inside the html, so the URL page is something like this
http://www.examplepage/conversations/44455
and when I click on another section of the page it it is
http://www.examplepage/conversations/44874
it changes not only at the end but like this
http://www.examplepage/settings
without doing post back and reloading the javascript so my question is, is there a way to detect those changes? and event listener but how?
I search and everyone says hash event but I don't have any value after any hash so it doesn't work
EDIT
Just for the record I have no code of the page nor I have access, I'll explain better, I am doing a background google extension and I just added a slide out to an existing page, this page changes its url the way I explained above. the url changes like every page does, but they change the div inside the html so that the page doesn't have to charge everything again
You need to store the URL when the page loads as a starting point and setInterval to check for changes and modify based on that.
The following code does this check twice a second (500ms):
// store url on load
let currentPage = location.href;
// listen for changes
setInterval(function()
{
if (currentPage != location.href)
{
// page has changed, set new page as 'current'
currentPage = location.href;
// do your thing..
}
}, 500);
There is no "clean", event-based way to detect such URL changes from a content script.
They are done with history.pushState API - and using that API doesn't emit any DOM event.
Two possible indirect event-based approaches, besides the already mentioned poll-based one:
An extension can override history.pushState with an injected script to additionally emit a DOM event that can be listened to in a content script.
This approach is described in detail here.
The downside is that, depending on the code of the page in question, the injected script may need to be injected early, needing run_at: document_start which is suboptimal for page load performance.
Use a background page that listens to chrome.webNavigation.onHistoryStateUpdated event.
If you need to detect this in a background page — perfect,
you're done, without ever needing a content script.
If you need to detect this in a content script, you can use details.tabId in the event listener to send a message to the right content script.
Related
Every time I click an <a> element with an anchor AND a JavaScript parameter, the URL doesn't change, the page just leads me to the anchor element. For example, when I'm on "website.com" and I click this hyperlink:
TEST
The page will scroll to the #anchor element but the URL will still be "website.com", so the JS parameter doesn't get any value. I tried to replace the code with this:
<a href="website.com/?par=123#anchor" onclick="window.location.reload(true)">
And the page reloads, but it only reloads after scrolling to the #anchor element and it still keeps on "website.com", so no success.
This is the whole purpose of URL hashes. It was initially designed to scroll to a particular id in the DOM and was also used by some SPA (Single Page Application) frameworks before the History API existed, as a solution to represent a JavaScript state in the URL.
As it represents a state of the web page in the browser, it's never sent to the server so the browser doesn't send the request again when it changes because the current URL (and thus the server-side resource) is considered unchanged.
If you want to execute JavaScript code in reaction to the hash change event, you can do like this:
window.addEventListener('hashchange', () => console.log(window.location.hash));
Foo
Bar
You can use par='123#anchor' instead par=123#anchor like this code and it works.
TEST
I have created a few variables for custom dimension on pageviews.
Pageview trigger: windowload or history change
The data is being pushed through, but it's only getting previous pages'
for example,
page/1 div class "page date" is 25th Jul, I would get undefined, but
when I click onto page/2, i would get the page/1's "page date"
function() {
return window.document.getElementsByClassName('page date')[0].innerText;
}
It seems that the history event is triggered before the corresponding page content is loaded into the DOM. This is nothing you can blame GTM for (GTM sees a history change, inspects the DOM, and grabs whatever it finds there, and that's the normal/expected behaviour).
Your solutions:
Make sure content is updated in DOM BEFORE the history event is triggered: this is something to sort out on the application side, and that may not be easily changed (if you use a framework like react it's probably best if you don't start hacking its core behaviour).
Delay the history event triggers: have a look at this solution which describes how to achieve this. Please note that solutions based on delays are never 100% reliable because there's a race condition between your delay and the loading of content, and you don't know for sure who will come first (and increasing the delay too much can cause the side effect of users changing pages in quick successions before analytics had a change to capture them).
Detect DOM changes: a more robust alternative would be to monitor the DOM for a particular element that is unique to each page (eg a <meta> element with the page ID or URL). You could use a tag to initiate the monitoring of this element when you receive the history change, and when the element actually changes it means the DOM has been updated, and you could fire your own trigger. This could be done via the MutationObserver or using a setInterval/setTimeout loop to check manually. However if the DOM is changed in several phases (blocks by blocks) this would not work (your <meta> element would have changed but not the div you're looking for), requiring you to start monitoring on a per-element or per-block level, which will be quite some work.
Push a dataLayer from your application: this would be my preferred option. I would hook into the logic of your application (you should be able to extend the routing method or the app framework should give you event listeners you can bind a custom function of yours with in which you can tell GTM that the page has been changed (eg dataLayer.push({'event': 'page_changed'});)
As far as I understand, until now frontend frameworks like Angular JS, Backbone JS were making use of the hash value. But react router doesn't necessarily need hash. Can someone explain me how does this work ?
I guess this must be simple, maybe preventing the default behavior on change of the URL.
I have no clue !
It is called "push-state routing" it makes use of the HTML5 History API
var stateObj = { foo: "bar" };
history.pushState(stateObj, "page 2", "bar.html");
Suppose http://mozilla.org/foo.html executes the preceding JavaScript:
This will cause the URL bar to display http://mozilla.org/bar.html,
but won't cause the browser to load bar.html or even check that
bar.html exists.
Suppose now that the user now navigates to http://google.com, then
clicks back. At this point, the URL bar will display
http://mozilla.org/bar.html, and the page will get a popstate event
whose state object contains a copy of stateObj. The page itself will
look like foo.html, although the page might modify its contents during
the popstate event.
If we click back again, the URL will change to
http://mozilla.org/foo.html, and the document will get another
popstate event, this time with a null state object. Here too, going
back doesn't change the document's contents from what they were in the
previous step, although the document might update its contents
manually upon receiving the popstate event.
Once we understood all this, we simply need to listen on the window's popstate events which will be trigger on every state change, be it triggered by clicks, pressing the browser back button and so on.
I have a situation where I have to manually decorate a specific link across my entire website with the Google Analytics linkerParam.
This is to pass the GA client ID from my main site over to my ecommerce site in order to maintain the session.
Normally this would occur automatically through the auto linker settings but there is a server-side redirect page that sits between my site and the ecommerce site.
That redirect page would pass along the GA client ID but it's never given a chance because it's a page on my domain and not the external domain. Auto linker won't work in that situation which is why I need to manually do it myself.
The solution that I've been given basically adds a javascript addEventListener to each link to the redirect page.
That solution does work.
Is it better to use the addEventListener for when people actually click on the specific link to only then decorate that link with the linkerParam?
Or is it better to simply modify each link when the page initially loads?
Thanks
In my custom linkers I decorate the link only after is has been clicked. My reasons (which you may or may not find convincing) are:
if a user hovers over a link I do not want him to see an attached client id
since search engines now execute javascript they might index decorated links
I can decorate links only after they are actually on the page (but I can attach a callback function to links that are created after the fact), so if a user leaves before DOM ready the link is not decorated
On a page with lot's of links decorating all of them actually takes some time and performance for something that I do not really need (after all I only need the clicked link decorated)
As to Ithans comment above (where I think he referred to the DOM rather than the sinister sounding "doom"), since the user leaves the page in any case after clicking the link (you would not decorate in-page linking), so multiple DOM operations are not an issue.
You can change all the links when the page load
something like
var linksToChange = document.querySelectorAll('.theLinkClass');
for (var item of linksToChange ) {
item.href= "http://google.es";
};
So, I have a page that has several links with onClick events that will retrieve data from external files and fill a div with this data. This works as intended. When I refresh the page, however, the div empties again. What I would like to happen is that after a refresh, the div will maintain the last content retrieved.
I'd prefer not to go down the road of cookies and have looked into adding data to the URL which I think is the way I want to go with this.
Is there some nice JQuery calls that can append data to url when a link is clicked and then on refresh restore the required content to the div?
My loadContent function is:
function loadContent (url, container) {
var target = $(container);
target.load(url, function (text, statusText) {
if (statusText === "success") {
target.find("a[rel^='gridnav']").initgn();
}
});
}
edit: I forgot to mention, the line
target.find("a[rel^='gridnav']").initgn();
is used to re-initialise a script on the new content loaded.
So when I click a link, the onClick event calls the function like this
TEST</li>
where xyz.html contains only the data I want inside the div "#right"
Is there a way to edit this function to do what I want ?
You can append data to the url by using
window.location.hash
https://developer.mozilla.org/en-US/docs/DOM/window.location
If you search for QueryString in jQuery plugins, there should be dozens of plugins that simplify this task.
I'd use localStorage. It's like cookies but much, much easier to maintain. The only downside is that it's not supported by all legacy browsers (See http://caniuse.com/#search=localStorage for browser support). For an orview on thhe feature, see https://developer.mozilla.org/en-US/docs/DOM/Storage If you want to go with completely no cookie like features at all; well then it has to be done server side to the best of my knowledge
Without cookies, your task will be a little bit harder. But I may have two solution for you:
Using session on server, you can control which ajax has been call, so next time when the main page is loaded, you can append the new content to it.
Using url hash to append ajax anchor has been click #anchorname so you can click it a gain after reload.
The comment tells you how you can modify the url without a page load. You could use that. If you have to work with older browsers, then you can still use the fragment (or do both things).
There are some history plugins for jQuery/JavaScript that manage this .. it's a technique called "deep linking." You may be able to find something simple to work with. Basically when loadContent runs you would want to update the url from /whatever to /whatever#right with the fragment indicating the load-content ID or something like that.
Another alternative would be to set some flag on the server that loads into that div when the page loads initially, which would save you an ajax request too. Depending on how your server code is set up that may not work for you, though.