set up Facebook Pixel only for production in ReactJS - reactjs

I am using React as my front-end (and Rails as my back-end).
I am setting up the Facebook Pixel Events Manager to track my Facebook ads on my website.
So I added this script to my public/index.html:
<!-- Facebook Pixel Code -->
<script>
!function(f,b,e,v,n,t,s)
{if(f.fbq)return;n=f.fbq=function(){n.callMethod?
n.callMethod.apply(n,arguments):n.queue.push(arguments)};
if(!f._fbq)f._fbq=n;n.push=n;n.loaded=!0;n.version='2.0';
n.queue=[];t=b.createElement(e);t.async=!0;
t.src=v;s=b.getElementsByTagName(e)[0];
s.parentNode.insertBefore(t,s)}(window, document,'script',
'https://connect.facebook.net/en_US/fbevents.js');
fbq('init', 'MYID');
fbq('track', 'PageView');
</script>
<noscript><img height="1" width="1" style="display:none"
src="https://www.facebook.com/tr?id=MYID&ev=PageView&noscript=1"
/></noscript>
<!-- End Facebook Pixel Code -->
and in my React Components I added this callback function anytime a button is clicked and raise an event:
() => fbq('track', 'MyEvent');
It seems to work, although I need my pixels to fire only in production. I can't access process.env.NODE_ENV in public/index.html.
What can I do to have this code used only in production ?

In most of my simple apps I choose to manage this by printing a JS variable into the html page. My prefer goto is Handlebars and I'll inject a config object into the header that will contain something like.
<script type="application/javascript">
var CONFIG = {
fbPixel: '{{ fbPixel }}'
}
</script>
The fbPixel comes from a config file and is only populated in staging and production environments. In development it's undefined/empty. Quick and simple to setup. In my more complicated apps I still basically do the same thing, but use a helper function in the middle for validation and allowing of default options.

thanks to #Dvid Silva and #Russ Brown, I finaly went with the following solution: create two separate index.html files: dev-index.html and prod-index.html
in my config/path.js:
module.exports = {
#[...]
appHtml: process.env.NODE_ENV === 'production' ? resolveApp('public/prod-index.html') : resolveApp('public/dev-index.html'),
#[...]
};
Both index files are identical except the production one has the Facebook Pixel inside its <head> tag.

an alternative solution: if you use git;
checkout from your "master" branch, and create a new branch called "dev":
git checkout -b dev
then on your "master" branch, reserved for production, inject the pixel code base. Checkout again to your dev branch and work there.
When you want to push new features into production, merge "dev" into "master", while keeping 2 versions of the file index.html

Related

Dynamically loading TokBox Embed script in ReactJS

I'm trying to dynamically load the TokBox embed script in my React app when the user clicks a button. The script tag is being added to the DOM and successfully loading but it does not go on to download opentok.min.js and thus the video control never renders. Adding the code directly into index.html works fine however. What is different about loading the tag dynamically?
Snippit:
import Script from 'react-load-script';
...
render() {
return (
<div>
...
<div id="otEmbedContainer" style={{width:"300px", height:"300px"}}></div>
{this.state.showVideo &&
<Script
url='https://tokbox.com/embed/embed/ot-embed.js?embedId=MYEMBEDID&room=' + this.state.roomId
/>
}
</div>
)
);
Response from TokBox support:
It is noted that when you load embed dynamically. you need to fire following event also after the dynamic loading( this is required for embedded to be loaded as per current design).
var DOMContentLoaded_event = document.createEvent("Event")
DOMContentLoaded_event.initEvent("DOMContentLoaded", true, true)
window.document.dispatchEvent(DOMContentLoaded_event).
I haven't tried this because I switched to use the iframe solution for now but posting here for continuity.

OnsenUI loads page in text, via a splitter

I have previously created a web app, and now I would like to integrate it with OnsenUI to enable my app to be used on all mobile devices as well as the web.
I am using a splitter in a toolbar which will be the header of all pages, and it will redirect the user to other pages when they click an item in it. Clicking the home item successfully redirects to the home page (index, which is already loaded correctly). However, clicking any of the other items in the splitter redirects me to the requested page, but shows the content of the file in text format instead of actually rendering the page. It looks like the following, except it's all jumbled together with no spaces:
searchForTrainer.jade:
//-ons-template(id='searchForTrainer.jade')
ons-page(ng-controller='SearchController' ng-init='showme = false; getAllTrainers();')
ons-toolbar
.left
ons-toolbar-button(ng-click='mySplitter.left.open()')
ons-icon(icon='md-menu')
.center
| Search Trainer
// ***** I cut off the rest of the file for simplicity
// ***** I should still be able to see the toolbar if the page loads correctly
Here is the content of index.jade:
doctype html
html
head
link(rel='stylesheet' href='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css')
link(rel='stylesheet', href='/stylesheets/style.css')
link(rel='stylesheet' type='text/css' href='/stylesheets/jquery.datetimepicker.css')
link(rel='stylesheet' type='text/css' href='/stylesheets/ratings.css')
link(rel='stylesheet' type='text/css' href='/stylesheets/searchTrainerTab.css')
link(rel='stylesheet' type='text/css' href='/onsenui/css/onsenui.css')
link(rel='stylesheet' type='text/css' href='/onsenui/css/onsen-css-components.css')
block loadfirst
script(src='https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js')
script(src="https://code.jquery.com/jquery-1.12.3.min.js"
integrity="sha256-aaODHAgvwQW1bFOGXMeX+pC4PZIPsvn2h1sArYOhgXQ=" crossorigin="anonymous")
script(src='/onsenui/js/onsenui.js')
script(src='/onsenui/js/angular-onsenui.js')
script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js')
script(src='/angular/fitnessapp.js')
script(data-require='angular-credit-cards#*', data-semver='3.0.1', src='https://rawgit.com/bendrucker/angular-credit-cards/v3.0.1/release/angular-credit-cards.js')
script(async='', defer='', src='https://maps.googleapis.com/maps/api/js?key=AIzaSyDcVf7YAPNwa8gUsMCOZNQZA31s5Ojf2n8&libraries=places')
body
ons-splitter(var='mySplitter', ng-controller='RootController as splitter')
ons-splitter-side(side='left', width='220px', collapse='', swipeable='')
ons-page
ons-list
ons-list-item(ng-click="splitter.load('index.jade')", tappable='')
| Home
ons-list-item(ng-click="splitter.load('searchForTrainer.jade')", tappable='')
| Search Trainer
ons-list-item(ng-click="splitter.load('searchForEvent.jade')", tappable='')
| Search Event
ons-list-item(ng-click="splitter.load('trainerAddEvent.jade')", tappable='')
| Create Event
ons-list-item(ng-click="splitter.load('userProfile.jade')", tappable='')
| Profile
ons-list-item(ng-click="splitter.load('addPayment.jade')", tappable='')
| Payment
ons-list-item(ng-click="splitter.load('userSettings.jade')", tappable='')
| Settings
ons-list-item(ng-click="splitter.load('trainerSignup.jade')", tappable='')
| Trainer Application
ons-list-item(ng-click="href='/logout'", tappable='')
| Logout
ons-splitter-content(page='index.jade')
ons-template(id='index.jade')
ons-page(ng-controller='MapController' ng-init='getEvents()')
ons-toolbar
.left
ons-toolbar-button(ng-click='mySplitter.left.open()')
ons-icon(icon='md-menu')
.center
| Fitness App
//-.right
a(href='https://www.paypal.com/webapps/mpp/paypal-popup', title='How PayPal Works', onclick="javascript:window.open('https://www.paypal.com/webapps/mpp/paypal-popup','WIPaypal','toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, width=1060, height=700'); return false;")
img(src='https://www.paypalobjects.com/webstatic/mktg/logo/bdg_now_accepting_pp_2line_w.png', border='0', alt='Now Accepting PayPal')
//- google maps stuff
ons-input#pac-input.controls(type='text', placeholder='Search Box')
div#map.col-md-12
ons-bottom-toolbar
.center
| Fitness App
block scripts
script.
// ***** I cut out javascript related to Google Maps for simplicity
here is the splitter load page function I am using in my angular file:
this.load = function(page) { console.log("The page is: " + page);
mySplitter.content.load(page)
.then(function() {
mySplitter.left.close();
});
};
Has anyone successfully built an Onsen app using Jade?
UPDATE
When I leave the code in html instead of jade, everything works correctly. When I convert it back to jade it shows up as text again.
UPDATE 2
Using Solution 1 from the selected answer, I realized and solved my problem with the guidance from the selected answer on my other post:
Answer
By the looks of it you seem to be using Jade on the server side.
To solve the problem I see a couple possible solutions.
Solution 1:
Make sure that whatever Onsen UI is receiving is pure HTML. You're free to use Jade, but as it stands Onsen does not have Jade bundled inside, so there is no way for it to support it out of the box. However as long as Onsen sees only html it should be fine.
The reason why the ons-template(id='index.jade') works initially is actually because when you serve the page you are actually serving actual html, so when onsen starts the contents of that template are actually pure html.
In searchForTrainer.jade it seems that you are giving it raw jade, which it does not know how to handle. You can handle this on the server side, making sure that the request for the searchForTrainer returns html. Returning jade.renderFile('searchForTrainer.jade') from the server instead of the jade file itself should solve the issue.
Solution 2:
As you noticed as long the contents are inside the initial page everything will be fine. So you could just put all your ons-templates inside the initial page.
If you want to retain your current file structure you can just do
include searchForTrainer.jade
while having an ons-template tag in the file itself. That way in the end the result will be a page with the template already converted into html.
Solution 3:
The final option is to give the raw jade files, but help Onsen understand Jade, so that it can use them properly. To do that you need to include jade.js and modify Onsen UI so that it uses it.
However since Onsen does not currently provide an official API for switching template engines whatever hack we use now might break in the future. It's possible that in the near future a feature like that may be implemented, but in order to do it now we need to wrap some of onsen's internal functions.
Here's a simple example to do it.
module.run(function($onsen) {
var old = $onsen.normalizePageHTML;
ons._internal.normalizePageHTML = $onsen.normalizePageHTML = function(html) {
return old(jade.render(html, {}));
};
});
And here's also a working Demo showing this solution in action.
Note: that demo actually checks for a comment // jade at the beginning just to be safe.
Which solution to choose?
Solution 1 - I think this makes most sense as it retains a clear separation of concerns. If you want to change the templating engine it should be handled only in one place. Onsen does not need to know what you're using on the server as long as it gets what it wants.
Solution 2 - Not the best way to solve the problem, but it may be the easiest to use if you just want things to work. One minus is that with it you would load all the templates at the beginning, which may not be very good.
Solution 3 - While this solution can work I would suggest avoiding it as handling jade on the frontend would result in poor performance. It's could be an option if you actually decide not to rely on the server.

lightbox2 maxwidth setup?

Speaking of lightbox2 version 2.8? downloaded march 2016...
How set maxwidth?
Here mi setup:
Under mi website folder i've, created a folder 'lightbox2' and put into the contain of the 'dist' folder of lightbox: css, images and js folders.
Then into de 'head'`section of html page, enter this code:
<link rel="stylesheet" href="lightbox2/css/lightbox.min.css">
<script>
lightbox.option({
'maxWidth' : 400,
})
<script>
and
<script src="lightbox2/js/lightbox-plus-jquery.min.js"></script>
at end of page
Now display the image with:
<img src=image-sample.jpg width=120 border=0>
The image always show at original size!
Help, please
well ... after searching and testing, I discovered that options should go under the line that invokes the js, not the css :)
After this, the image limit size work ok.

AngularJS w/ noscript

I am attempting to create a SPA using AngularJS as the main view for my website. I'm using ServiceStack on the server-side and can therefore cleanly serve HTML or JSON requests depending on what's accessing it. My main concern is the use of script blockers, preventing AngularJS from rendering the page properly. So far my main way of working is to render static pages, and inject a small script that redirects to the AngularJS-powered pages if it detects if Javascript is enabled. This works great since every URL works fine when the user begins at the static pages, but I've ran into a couple of snags.
Browsing to a link which includes the "?View=SPA" breaks the page if JavaScript is disabled
This causes the first page loaded to be loaded twice.
I'm looking for an alternative, but so far I haven't found any clean solutions. I was thinking about including the "?View=SPA" as a POST variable, but I'm still iffy on that implementation.
Any thoughts?
Instead of redirecting to an other page, I would implement both cases in the same HTML File as follows:
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<style>.hideIfNoScript {display: none}</style>
</head>
<body ng-app ng-init="msg = 'hello world'">
<input class="hideIfNoScript" ng-model="msg" />
<p class="hideIfNoScript">{{msg}}</p>
<noscript>
<p>Content without javascript</p>
</noscript>
<script type="text/javascript">
var myEl = angular.element( document.querySelectorAll( '.hideIfNoScript' ) );
myEl.removeClass('hideIfNoScript');
</script>
</body>
</html>
The CSS Class hideIfNoScript in the head section makes sure that all HTML Tags with this class are never shown to the user, if javascript is disabled.
The noscript tag shows the alternative content.
If javascript is enabled, the little script at the end of the body section makes those elements visible. And in this case, the contents of the noscript tag are hidden.
Browsing to a link which includes the "?View=SPA" breaks the page if JavaScript is disabled
Hide those links by default:
a[href*='SPA'] { display: none; }
This causes the first page loaded to be loaded twice
Use a cookie on a browser-check page which loads the first page in an iframe or redirects to it to avoid this.
References
Track Non-JavaScript Visits In Google Analytics

How to integrate AngularUI to AngularJS?

Sorry for the silly question, does everyone know how to start using AngularUI? I've downloaded it from Github and read the instruction in README but still don't understand what I have to do.
Steps to integrate:
Include jQuery and jQuery-ui (best served from a CDN)
Include angular (it is the best to include if from a CDN)
Include angular-ui JS / CSS (currently only hosted in the GitHub repository in the build folder)
Include any jQuery plugins for the directives you are planning to use
Declare dependencies on the angular-ui modules (ui.directives or ui.filters depending on what you are planning to use).
Most of the outlined steps are just about including JS/CSS dependencies. The only "tricky" part is to declare dependencies on a ui.* module, you can do it like this:
var myApp = angular.module('myApp',['ui.directives']);
Once all the dependencies are included and a module configured you are ready to go. For example, using the ui-date directive is as simple as (notice the ui-date):
<input name="dateField" ng-model="date" ui-date>
Here is the complete jsFiddle showing how to use the ui-date directive: http://jsfiddle.net/r7UJ2/11/
You might also want to have a look at the sources of the http://angular-ui.github.com/ where there are live examples off all the directives.
As of 3rd of May 2013, here are the steps:
include
<script src="angular.min.js"></script>
<script src="ui-bootstrap-tpls-0.3.0.min.js"></script>
register ui
angular.module('myFancyApp', ['ui.bootstrap']);
make sure myFancyApp is the same as in your <html ng-app="myFancyApp">
Let the magic commence.
I think what is missing is plugins - you've got to add the jquery plugin scripts and css for some angular-ui directives to work. For example the codemirror directive needs:
<script src="http://codemirror.net/lib/codemirror.js" type="text/javascript"></script>
<script src="http://codemirror.net/lib/util/runmode.js" type="text/javascript"></script>
<link rel="stylesheet" href="http://codemirror.net/lib/codemirror.css" type="text/css" />
It's a surprise to me that angular-ui.github.com doesn't mention needing to include plugins.
Hi I wrote an article specifically on how to do this for for PHP syntax highlighting. The article is here: http://neverstopbuilding.net/how-to-integrate-codemirror-with-angular-ui/
The core of things is getting the configuration right:
var myApp = angular.module('myApp', ['ui']);
myApp.value('ui.config', {
codemirror: {
mode: 'text/x-php',
lineNumbers: true,
matchBrackets: true
}
});
function codeCtrl($scope) {
$scope.code = '<?php echo "Hello World"; ?>';
}
For something like the following HTML snippet:
<div ng-app="myApp">
<div ng-controller="codeCtrl">
<textarea ui-codemirror ng-model="code"></textarea>
</div>
</div>
You can see the whole jsfiddle of the set up here: http://jsfiddle.net/jrobertfox/RHLfG/2/
pkozlowski.opensource is right, there are a lot more files that you need to include than it seems from the AngularUI documentation (if you can call it documentation...)
The instructions are in the readme.md file at their official github repository
Angular UI
Alternatively, the way you can find out how to integrate is to open the angular-ui js file (example: ui-bootstrap-tpls-0.6.0.js) and in the first line, you will notice the following statement
angular.module("ui.bootstrap", [...deps...])
Based on the above code, you need to inject 'ui.bootstrap' into your module.
angular.module('myFancyApp', ['ui.bootstrap','other_deps',.....]);

Resources