Google AdWords click conversion is "unverified" - asp.net

I've got an online store build on ASP.NET web forms. When a customer goes to the checkout page, there is a form, where they have to provide their details, like postage address etc. After they filled the form in they have to click "Pay now" button to be prompted to go to Paypal checkout page.
I need to track those clicks for the Google AdWords conversion statistics.
The usual code for tracking clicks would look like:
// some data
goog_report_conversion = function(url) {
goog_snippet_vars();
window.google_conversion_format = "3";
var opt = new Object();
opt.onload_callback = function() {
if (typeof(url) != 'undefined') {
window.location = url;
}
But because of the way the website was implemented, the destination link is being generated dynamically, so I couldn't pass it as as argument for "goog_report_conversion".
So I've slightly changed the conversion function to this:
// some data
goog_report_conversion = function(id) {
goog_snippet_vars();
window.google_conversion_format = "3";
var opt = new Object();
opt.onload_callback = function() {
if (typeof(id) != 'undefined') {
// I use custom function to trigger click on the actual button
event_fire(document.getElementById(id), 'click');
}
}
And I have this HTML structure:
<span class="GeneralFormButton" onClick="goog_report_conversion('submit_all')">Pay Now</span>
<input type="button" name="submit_all" value="Pay Now" onclick="this.disabled=true; this.value='Plase wait';__doPostBack('submit_all','')" id="submit_all" style="display: none;" />
Where <span> is being used to trigger the conversion function and then to emulate "click" on the actual submit button.
It works well and the customer is redirected to Paypal. However, the conversion isn't tracked and in Google AdWords account my "Pay with Paypal" option is marked as "Unverified" (It's been going for a way longer than 24 hors)
I tested what data is sent to google on submit:
https://www.googleadservices.com/pagead/conversion/*correct conversion id*/?random=1459744659796
&cv=8
&fst=1459744659796
&num=1
&fmt=3
&label=*correct conversion label*
&guid=ON
&u_h=800
&u_w=1280
&u_ah=777
&u_aw=1280
&u_cd=24
&u_his=11
&u_tz=570
&u_java=false
&u_nplug=5
&u_nmime=7
&frm=0
&url=http%3A//www.website.com/store_checkout2.aspx%3Fpay_service%3DPayPal%26promo_code%3D%26voucher%3D
&ref=http%3A//www.website.com/store_checkout2.aspx%3Fpay_service%3DPayPal%26promo_code%3D%26voucher%3D
&tiba=Contact%20and%20Delivery%20Address
&async=1
The conversion id and label are correct, the rest of the data seems to be okay too, but the conversion is still not tracked. I just can't figure out why.
Where did I go wrong and what do you think needs to be changed?
Thanks very much in advance

It turned out that the form was never completed and sent before, therefore Google couldn't verify the code. While I was testing for response data I sent the form and the code got verified.

Related

Track GA4 custom event

I am sending a custom event ("ebook") with a parameter ("titolo") to GA4. After that, I have set the parameter as a Custom Dimension in GA UI.
I am sending the event from my website with this code:
function ebooksGA4new(title) {
gtag('event', 'ebooks', {
'titolo': title
});
}
Then I have set an Exploration on the custom dimension, but after 3 days it still reports "not_set. If I fire the event, I can see it in the real-time report.
Here are 2 ways to find out why
Modify the code a bit, make sure it won't trigger the event if it doesn't have title parameter.
But please make sure this is what you want. You need to decide it is ok or not to receive the event without title parameter.
function ebooksGA4new(title) {
if(!title || title=="")
return false;
gtag('event', 'ebooks', {
'titolo': title
});
}
Open the chrome devtool or something similar with it. Here is the screenshot about how to check it. This should appear on your GA4 real time report as well.

Autofill an external form in an iframe from... another form

I'd like to point your kind attentions to my question, topic should be similar to this post.
In a WP website i have two columns:
Column n.1 There is a CF7 form that is autofilled by an url from a CRM and injects data to a GSheet.
Column n.2 There is an iframe for booking an appointment with an external calendar tool that should pick data from the form (i have no way to edit form, but just the iframe link, for example:
Is there the possibility for this link to "pick" the data from the form or also from the crm url? Do you think that is possible or am I a fool?
Many thanks for your help :)
You should look into using JavaScripts postMessage() functionality to pass data to/from iFrames.
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
Use something like this on the WordPress page
// This will get the value of the input and send it to the iFrame on the fly
$('#form-id input:not([type=submit])').each(function() {
var val = $(this).val();
$(window).postMessage(val);
});
Then on the iFrame page:
// Create browser compatible event handler.
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";
// Listen for a message from the WP page
eventer(messageEvent, function(e) {
if (e.data.length < 1) return;
// jQuery
$('#input-id').val(e.data);
// Pure JS
document.getElementById('input-id').setAttribute('value', e.data);
}, false);
If the forms on different domains I think this is the only method for doing this.

Social shares tracking in GA

This is pretty much covered topic for original FB/Twitter buttons. But what if I have my own "share on fb" button? Like this:
<div id="fb_share"><a target="_blank" href="http://www.facebook.com/share.php?u=blah-blah">Share on FB</a></div>
so I've come up with the folloing solution:
var FBbtn = document.getElementById("fb_share");
FBbtn.addEventListener('click', function() {
ga('send', 'social', {
'socialNetwork': 'facebook',
'socialAction': 'share',
'socialTarget': window.location
});
//console.log('tracked');
});
That is placed AFTER the Google Analytics code.
Despite the fact it wont catch FB callback - it is supposed to do the trick but for some reason I still cannot see any results in Analytics so the question is this: will the solution actually work? In fact it could be even like this I believe:
FB
Your 'share on Facebook' links causes the page to navigate (and not open a new window/tab). When this navigation happens, most mainstream browsers cancel all pending HTTP requests for the current page and then navigates to the new page (fb.com)
In this scenario, one of the pending HTTP requests will be the GA event tracking call which will therefore never complete and never be received by the GA servers.
What you need to use is the GA hit callback functionality, this essentially cancels the native navigation (to FB), sends the tracking call and waits enough time for it to complete and then does a JavaScript redirection to the next page.
You should read the google docs here
In your case your event tracking function should be similar to this:
var FBbtn = document.getElementById("fb_share");
FBbtn.addEventListener('click', function() {
ga('send', 'social', {
'socialNetwork': 'facebook',
'socialAction': 'share',
'socialTarget': window.location,
'hitCallback': function(){
window.location = this.href;
}
});
//console.log('tracked');
return false;
});
So I've made the following changes:
Added the hitCallback property to the event tracking call. this is an anonymous function that is called once the GA servers have sent their response to the event tracking.
added a 'return false' statement which cancels the native functionality and then relies on the hitCallback function to do the navigating.

Meteor JS & Blaze - Show Only Once on Load

I have a partial that show's a notification modal to agree to the site's terms and service that I would only like to show once (once they click I agree it goes away).
Is there anyway to do that with Meteor?
Assuming you want to store a boolean in the DB indicating that the user has accepted the terms (so they never get asked again), you could add a field called hasAcceptedTerms somewhere on the user object (e.g. in the user's profile). Once you do that you could write your template like this:
<template name="myTemplate">
{{#if areTermsVisible}}
(put terms partial here)
{{/if}}
</template>
Where areTermsVisible looks like:
Template.myTemplate.helpers({
areTermsVisible: function() {
var user = Meteor.user();
return user && user.profile && !user.profile.hasAcceptedTerms;
}
});
And the code to record the acceptance looks like:
Template.myTemplate.events({
'click .accept-terms': function() {
var userId = Meteor.userId();
var modifier = {$set: {'profile.hasAcceptedTerms': true}};
Meteor.users.update(userId, modifier);
}
});
Maybe not surprisingly, the best way to deal with cookies policy notification is by using cookies. The problem is not meteor-specific, but there are at least two good atmosphere packages that can help you to deal with the problem:
https://atmospherejs.com/mrt/cookies
https://atmospherejs.com/chuangbo/cookie
What you need to do is basically, set cookie
Cookie.set('userHasAcceptedPolicy', true, { year: 1 });
with whatever arguments you like, and as soon as the user clicks the "accept" button. Then, before you decide if you need to show the policy notification you can use:
Cookies.get('userHasAcceptedPolicy');
to see if there's a need to do so. So it's pretty much the same solution as #DavidWeldon suggested but it does not require referencing the Meteor.user() object, so the user does not need to have an account to accept the policy.
Please note, that - at least in case of mrt:cookies - Cookies.get is a reactive data source, which is quite helpful when it comes to rendering templates.
There's plenty of ways...
This isn't a Meteor specific question.
Template.notifications.events({
'click #close-modal': function(e, t) {
$('#modal').hide();
}
})

grails controller/action/id automagically turning into controller/index

My problem is that the backend server (written in grails) is automatically converting my request URL to be a different URL. Specifically, it is changing it from /UXChallengeAwards/processSelectedNotifications to /UXChallengeAwards/index.
--
In a template gsp file, I have defined a button that makes a jQuery ajax call when clicked on:
<button class="blue-link"
onclick="jQuery.ajax({type:'POST',
data:jQuery(this).parents('.multiSelectForm').serialize(),
url: '/ici/UXChallengeAwards/processSelectedNotifications/${challenge.id}',
success:function(data,textStatus){},
error:function(xhr,textStatus,errorThrown){}
})" >
The method UXChallengeAwardsController.processSelectedNotifications exists. It performs some work and then redirects to another action in the controller. In fact, this used to work. But somehow in the process of adding a second button I made a change which seems to have broken things.
When the button is now clicked, the request URL gets switched to /ici/UXChallengeAwards/index and a 404 is returned because index does not exist as an action in this controller.
I've googled, and the most common answer for when this happens is that a controller must return some results for the view. But I've seen plenty of examples of redirects in controllers, and I do not see what I am doing wrong. (I did try variants of rendering results, but with no success.)
Here is what my controller action looks like:
def processSelectedNotifications = {
def challenge
def checkboxes = params.list('selectCheckbox');
for (checkbox in checkboxes) {
// the checkbox contains the id of a ChallangeAward that should be published
ChallengeAwards challengeAwards = ChallengeAwards.get(checkbox.toInteger())
if (challengeAwards) {
// grab a challenge for use in the redirect, they are all the same
challenge=challengeAwards.challenge
publish(challengeAwards)
}
}
if (challenge) {
redirect action: 'challengeAwardsRemote', id: challenge.id
return
}
// render a failure message if we got here
render messageNS(code:"UX.ChallengeAwards.Publish.failure")
}
I would really appreciate any insights into what might be wrong, or how to go about tackling this issue. I've checked my UrlMappings, and this is the rule that should handle this controller/method request:
"/$controller/$action?/$id?"{ constraints {} }
Thank you very much!
I'm going to go ahead and answer my own question, in case it is helpful for other newbies.
It turns out that I was not getting an automatic redirect. Rather, I had an error in the button setup code, so that grails was using its default link behavior. (Which is to go to the controller that matches the view, and if no action is specified, use the index method.)
The code above was originally created using a remoteSubmit tag, but I found that the generated code did not support handling multiple forms on a single page very well. So, I copied that generated code and then tweaked it to handle the multiple forms. However, I wanted the styling to match up with what was already in place on the page, so I switched it to be a button. That's when things went awry.
Eventually, I ended up specifying an onClick function for the button, and then writing the ajax submit code in javascript. Which turned out to be much simpler.
Here is what the button specification ended up looking like:
<button type="submit" id="notifications" class="blue-link" >
<i class="fa fa-envelope-o"></i>
<g:messageNS
code="UX.DiscussionBoard.ChallengeAward.Button.notify" />
</button>
And the associated JavaScript:
jQuery(document).ready(function() {
var clkBtn = "";
jQuery('button[type="submit"]').click(function(evt) {
clkBtn = evt.target.id;
});
jQuery('.multiSelectForm').submit(function() {
var url = '/ici/UXChallengeAwards/processSelectedNotifications';
if (clkBtn == 'deletes') {
url ='/ici/UXChallengeAwards/processSelectedDeletes';
}
var errorTarget = jQuery(this).parents().find('.recipientMessage').val();
var requestData = jQuery(this).parents('.multiSelectForm').serialize();
var options = {
data : requestData,
type : 'POST',
url : url,
target : '#awardsTab',
error : function(data) {
jQuery('#' + errorTarget).html(data.responseText).show();
},
success : function(data) {
console.log("in success");
}
};
jQuery(this).ajaxSubmit(options);
return false;
});

Resources