How to use multiple ReactPixel.track('abc') inside one component? - reactjs

I have a component on which I have to add two ReactPixel.track('abc') and
ReactPixel.track('cba'), how can I achieve this? Do I need to add just one ReactPixe.init('id') or two? Here is a code example:
componentDidMount() {
const options = {
autoConfig: false,
};
ReactPixel.init('123123', options);
ReactPixel.pageView();
ReactPixel.track('abc');
ReactPixel.track('cba');
}

You don't need to add multiple React inits on every page.
Just add it on your App.js(If you use create-react-app).
* You should initiate before you use it.
ReactPixel.init('123123', options);
If you need to get pageview details of whole app you need to use the below code.function in entry level.(I prefer after the init function)
ReactPixel.pageView();
There is no magic. It just call the same function that Facebook has given to you. fbq('track', 'PageView');
You can use track codes inside your functions. As a example after registration is successful you can create this track code.
ReactPixel.track('abc',{#data object goes here});
This is the example that Facebook has given.
fbq('track', 'Purchase',
// begin parameter object data
{
value: 115.00,
currency: 'USD',
contents: [
{
id: '301',
quantity: 1,
item_price: 85.00
},
{
id: '401',
quantity: 2,
item_price: 15.00
}],
content_type: 'product'
}
// end parameter object data
);
You can use this same function with react-facebook-pixel wrapper like this.
ReactPixel.track('abc',{#data object goes here});
Tracking Custom Events
You can track custom events by calling the pixel's fbq('trackCustom') function, with your custom event name and (optionally) a JSON object as its parameters. Just like standard events, you can call the fbq('trackCustom') function anywhere between your webpage's opening and closing tags, either when your page loads, or when a visitor performs an action like clicking a button.
For example, let's say you wanted to track visitors who share a promotion in order to get a discount. You could track them using a custom event like this:
fbq('trackCustom', 'ShareDiscount', {promotion: 'share_discount_10%'});
you can track custom events with react wrapper like this
ReactPixel.trackCustom(#title_of_event,#data_object);
If you need more understanding of what this react-facebook-pixel has done. You can read the code of the package.
https://github.com/zsajjad/react-facebook-pixel/blob/master/src/index.js
Facebook documentation: https://developers.facebook.com/docs/facebook-pixel/implementation/conversion-tracking#advanced_match

Related

Should I store static configuration in redux?

I am building a react/redux web app and am wondering where I should static configuration information that never changes (while the webapp is running anyway).
This is the data in question
This information is used in different parts of the app, for example: there is a form where you are able to select any item out of the main array, and by doing so populating another select field with properties of the selected array:
<select>Choose an exchange</select>
<select>Choose a market (that is available in the above exchange)</select>
This would lend itself nicely to some reducer logic (that sets state.markets based on what is selected in the first select), but should it filter based on other state in the tree, or just load the data in a closure inside the reducer (keeping everything unrelated outside of state tree)? Or is this not state at all (and should the container load this file in and filter based on a single state.exchange state prop)?
When the form is filled in the result will be handled like:
{exchange: 'a', market: 'b'}
So that would be state too (I guess?)
My understanding of redux is that we should only be storing stateful data in the store, that is, data that is subject to change. Static data by definition does not have state, and therefore does not need to be tracked as such.
As a result, I typically have a /common/app-const.js file where I store these types of static objects. In your case, you can simply move all the static data from exchange.js into a common file that you then import wherever you need it.
/common/app-const.js
export default {
markets: [
{ pair: ['USD', 'BTC'], minimalOrder: { amount: 0.01, unit: 'asset' } },
{ pair: ['RUR', 'BTC'], minimalOrder: { amount: 0.01, unit: 'asset' } },
{ pair: ['EUR', 'BTC'], minimalOrder: { amount: 0.01, unit: 'asset' } },
...
}
I understand your approach however, it would be nice to simply inject your data, by way of connect() via react-redux, however its a bit more straightforward to just import the static data from a file where needed.

Passing a Complex Parameter into a Query in AngularJs

I have seen 100 examples of passing an ID into $resource.get() in order to query information out of a back-end in Angular. What I have not been able to find is how to pass a complex object.
If I have a table of objects to return, and I wish to run a search against them using multiple items of filter, I need to pass those items as parameters or as one complex parameter. For example, say I have a table of people's names and their cities, states, etc. I want to be able to say something like this:
var myResource = $resource(url);
myResource.get({name : "Mike", state : "Texas"});
The return may be a single row or multiple rows. But the point is how do I get the parameters off to the API call?
The way I have other methods set up that are simpler is by creating a repository in which I return like so:
return resource('/api/broker/productionInfo/');
Then in my API I do this (after the [RoutePrefix("api/broker")] setup:
[HttpGet]
[Route("productionInfo")]
public IHttpActionResult GetProductions()
{}
That's all awesome but I want to be able to add the search criteria in the repository call and then in the API method (i.e. extract from a querystring or however it is to be passed).
If I understand what you are asking correctly, you just want to pass additional parameters into an angular resource get request. It is as simple as what you have already suggested:
resource.get({id: 1, custom_param_1: "param1", custom_param_2: "param2"});
This would result in an http request that looks like this:
/resource/1?custom_param_1=param1&custom_param_2=param2
You can then extract these parameters on the API side of things.
Something to note is that get requests have a maximum length, and if you are attaching lots of different parameters to the request, it may be better to use a post or put instead.
The only thing I'm seeing that you're missing is a [FromUri] decorate attribute, in your GetProduction API method. Since Get supports only params binding through a query string (no body binding).
Your params:
options: {
StartDate: _startDate
EndDate: _endDate
TextSearch: "some search query....",
Page: 1,
PageSize: 25,
et...
}
Then, calling your repository from your controller:
repository.get(options).$promise.then(function (data) {
// data = response payload from backend
});
reposiroty
....
return resource('/api/broker/productionInfo/');
....
API
[HttpGet]
[Route("productionInfo")]
public IHttpActionResult GetProductions([FromUri] SearchCriteriaModel criteria) {
....
}
Hope that helps.

React/Flux app data structure

i'm building an Gmail-like email browser client app prototype and i need a little help/advice structuring my React/Flux app. I decided to use pure Flux to get a better idea of how it works.
It's a simple email client with a list of letters, grouped by folders and tags and an ability to add letters to favorites.
So, i have a LettersStore containing an array of letters. The single letter data object looks something like this
{
id: 0,
new: true, //unread
checked: false,
starred: false,
folder: "inbox", //could be 'sent', 'spam', 'drafts'
sender: "Sender Name",
subject: "Re:",
snippet: "Hello there, how are you...",
body: "Hello there, how are you doing, Mike?",
date: "02.19.2016 16:30",
tags:["personal", "urgent"]
}
So what i'm trying to achieve is to let users navigate through folders (inbox, sent, drafts, spam) and filters (starred, tag, etc.)
In both folders and filters there has to be a way to select (check) some/all letters. The view state depends on how many letters are selected (the Select-all checkbox update, just like on Gmail). When the user selects a letter, the Flux action is being triggered and the state of the app updates.
The controller-view on top of the app does all the calls to the LettersStore public methods and passes the data down as props, but i'm not sure, what public methods the LettersStore should have. Currently it has:
emitChange()
addChangeListener()
removeChangeListener()
getAll() //returns array
areSomeLettersInFolderChecked(folderName) //returns bool
areAllLettersInFolderChecked(folderName) //returns bool
countNewLettersInAllFolders() //returns object
This works ok with folders, but when it comes to filters, it doesn't make sense anymore, since a starred letter is in some folder, and i feel like it's not the right thing to add specific methods like areSomeLettersInFilterChecked(filterType) etc.
Also, just like in Gmail, there has to be a way to select letter in the "Starred" filter, which belongs to the "Inbox" folder, then navigate to "Inbox" folder and keep that letter selected.
Maybe i should move the areSomeLettersInFolderChecked-like stuff to the component level?
I'm sure here has to be a proper way of doing it. Thanks in advance!
Rather than trying to encapsulate all the possible states and filters into your letter objects, keep it dumb. Normalize it and use supporting data structures to represent the other characteristics.
I'd strip it down to just the following properties:
{
id: 0,
sender: "Sender Name",
subject: "Re:",
snippet: "Hello there, how are you...",
body: "Hello there, how are you doing, Mike?",
date: "02.19.2016 16:30",
tags:["personal", "urgent"]
}
Your LetterStore can stay the same, or alternatively you could use an object or map to store letters against their id's for quick lookups later.
Now we need to represent the properties we removed from the message.
We can use individual sets to determine whether a message belongs to the new, checked and starred categories.
For instance, to star a message, just add it's id to the starred set.
var starred = new Set();
starred.add(message.id);
You can easily check whether a message is starred later on.
function isStarred(message) {
return starred.has(message.id);
}
The pattern would be the same for checked and unread.
To represent folders you probably want to use a combination of objects and sets.
var folders = {
inbox: new Set(),
sent: new Set(),
spam: new Set(),
drafts: new Set()
}
Simplifying your structures into these sets makes designing queries quite easy. Here are some examples of the methods you talked about implemented with sets.
function checkAll() {
messages.forEach(function(message) {
checked.add(message.id);
});
return checked;
}
function isChecked(message) {
return checked.has(message.id);
}
function inFolder(name, message) {
return folders[name].has(message.id);
}
// is message checked and in inbox
if(isChecked(message) && inFolder('inbox', message)) {
// do something
}
It becomes easy to construct complex queries, simply by checking whether messages belong to multiple sets.

Marionette Regions and routing

I'm using a LayoutView to display a collection in table form. When a user clicks on a tr I swap the CompositeView for an ItemView that shows the details using the same region. It all works except the functionality of the back button is broken. Is there a way to trap the back event and switch views?
Or should I use two Views and pass the model id and then refetch the model? The problem with that though is the extra request and I lose the filter and sort values of the table unless I use local storage.
Including more code would be better, but in any case I will try to give some guidance for your problem.
To avoid fetching the data twice, you can keep a common object in a "parent" component, for example in the Router.
var theObject;
var router = Marionette.AppRouter.extend({
routes: {
"routeA/:id": "goToRouteA",
"routeB/:id": "goToRouteB"
},
goToRouteA: function(id) {
MyRegion.show(new myLayout({
model: this._getCommonObject(id)
}));
},
goToRouteB: function(id) {
MyRegion.show(new myLayout({
model: this._getCommonObject(id)
}));
},
/*Return the common object for the views*/
_getCommonObject: function(id) {
theObject = (theObject && theObject.get('id') == id) ? theObject : MyApp.request('getTheObject');
return theObject;
}
});
In this way, you can keep the reference to the same object without loosing information.
You just have to make sure to delete the object when it is not needed to avoid keeping old information, for example on the Region close event.

Get items which are part of the same group in Firebase

I have a simple data structure of users and events. I am wanting to find all users who are attending the same events that the logged in user is. Users can attend multiple events.
My data is setup as follows
{
events:{
123:{
name: 'event1',
users:{
9876: true,
7564: true
}
}
},
users:{
9876:{
name: 'John',
events:{
123: true
}
},
7564:{
name: 'Peter',
events:{
123: true
}
}
}
}
I have the following code to achieve this, I was just wondering if I am on the right path and if my data structure is correct for this type of query (Firebaseref is an Angular factory)
FirebaseRef.child("users/" + authData.uid + "/events").orderByChild('displayName').once("value", function (snap) {
snap.forEach(function (event) {
FirebaseRef.child("events/" + event.key() + "/users").once("value", function (userSnap) {
userSnap.forEach(function (user) {
FirebaseRef.child("users/" + user.key()).once("value", function (realUserSnap) {
if (realUserSnap.key() != authData.uid) {
//This is a user who attends the same event
}
});
});
});
});
});
I would probably change that outermost query from a once('value' to an on('child_added' (and its other child_* siblings). The main advantage is that you're monitoring/synchronizing the data, instead of retrieving is just once. An added advantage is that it will remove the need for your first forEach.
Aside from that, this looks pretty common. The inner calls need to be once's, because you only want them to execute once. Most people get nervous because of the number of the number of on calls that will happen. But Firebase's data retrieval has little overhead after the initial websocket connection has been set up, so this typically performs pretty well.
There are lots of "should", "typically" and "may" in this answer, since the only way to be certain is for you to actually:
verify that the code functionally does what your application requires
measure the performance of the code in the conditions that you expect your users to encounter
If you do run into higher-than-expected latency, you could consider denormalizing the data a bit further. For example: you could keep the user's name in each event, where you now store true. With that, you would need to look up each user's name.

Resources