Browsing Category

Méthodo

Ma Première Application Javascript

Présentation

Dans le cadre de ma formation à Ironhack, je dois réaliser un projet final en javascript qui reprend tous les concepts traités lors des précédentes semaines. Mongo, Express, Vue & Node : tout y passe. À ces fins, je souhaite retranscrire jour après jour la manière dont je vais développer cette application.

mevn-javascript

Ce journal de développement a également pour but de montrer à tous mes lecteurs no-tech qu’il est possible de rapidement se mettre à niveau et de pouvoir développer ses projets. Bien évidemment, il reste pas mal de chemin à parcourir avant de pouvoir maintenir une application grand public, mais réaliser un MVP est dorénavant tout à fait jouable.

Ainsi, lors des deux prochaines semaines, je tâcherais d’éditer quotidiennement cet article afin de vous donner tous les détails de ma démarche.

Pour ce projet, j’ai souhaité réaliser une application de dating.

Problématique

Tinder a frappé un grand coup en imposant un standard sur les applications de rencontre : le swipe. Cependant, des applications ont réussi à se frayer un chemin sans utiliser cette fonctionnalité. Je pense notamment ici à Happn qui s’adosse sur la géolocalisation de ses utilisateurs.

Toutefois un outsider, Bumble, réussit à sortir son épingle du jeu. La feature #1 est la suivante : les filles amorcent les discussions sous 24h après le match sinon la mise en relation est supprimée.

Il est intéressant également de citer Abricot qui réinvente l’agence matrimoniale et qui rencontre un succès conséquent auprès des femmes.

Suite à quelques interviews, j’ai pu détecter, auprès des filles, que les applications (comme Tinder qui n’émettent aucun type de restrictions) ont de moins en moins le vent en poupe. On a tous ce pote qui est capable de liker 300 matchs / seconde :)

En effet, il existe un déséquilibre majeur entre les aspirations des femmes et des hommes sur ce type d’application. Le comportement des hommes est parfois perçu comme déplacé par les femmes.

Données

Aujourd’hui, près d’une parisienne sur deux est célibataire. – source : étude ifop – lci

Les applications de rencontres sont démocratisées chez les jeunes (28% des 18-25 ans) et chez les CSP+ (16,3%) – source : BVA

Les utilisateurs n’hésitent pas à avoir plusieurs applications – source interviews

Une personne sur deux avoue à son entourage sa présence sur une application.  – source : BVA

Il est plus facile de faire venir des hommes sur une application mobile que des femmes. – source : interviews & intuition :)

Réponse

Dans un souhait de rendre l’application plus authentique que le niveau moyen, l’idée est ici de contraindre le swipe grâce à un quizz.

Exemple : Je suis l’utilisateur A, je trouve les photos et la description de l’utilisateur B intéressantes, je like ce profil et l’application m’impose de répondre à un quizz, préalablement édité par B, avec des thèmes comme la musique, les films, les voyages ou encore les livres. Si mon taux de réussite est satisfaisant, B sera notifié que je souhaite rentrer en relation avec.

QCM

Véritable pierre angulaire de ce projet, ce quizz a donc vocation d’augmenter la friction sur la mise en relation. Des questions à choix multiples permettent ici de rendre cette fonctionnalité possible à la fois sur un plan d’expérience utilisateur que sur un plan technologique.

En connectant les API de Spotify, IMDB, Google Places et Books il est possible de traiter des cellules très classiques comme :

  • Musique : quel est ton artiste préféré ? quelle est ta musique du moment ?
  • Cinématographie : quel est le film qui t’a le plus marqué ? qui est ton acteur favori ?
  • Voyages : ta destination de vacances préférée ? ton prochain voyage ?
  • Littérature : quel est ton livre de chevet en ce moment ? l’auteur qui t’a le plus inspiré ?

Seuil

L’utilisateur a toutefois la possibilité de garder un contrôle sur cette friction en déclarant un % de réussite minimum/maximum.

Par exemple, un utilisateur qui souhaite recevoir des notifications uniquement en provenance d’autres utilisateurs qui ont réussi à remplir parfaitement le quizz. À l’inverse, un utilisateur pourrait décider d’être notifié sans une seule réponse juste à son quizz.

L’utilisateur gardant, bien entendu, la possibilité d’accepter ou non la mise en relation.

Si l’utilisateur valide, la messagerie sera activée pour cette connexion. Le concept de l’application permet également de briser la glace plus rapidement grâce au quizz préalablement rempli.

Exemple :

Toi aussi tu es fan de Tarantino ?

Technologies employées

Pour arriver au résultat escompté, voici les ensembles technologiques que je vais utiliser :

  • Database : MongoDB + Mongoose
  • Back : Nodejs + Express
  • Front : Vuejs + Vuerouter
  • Mobile : React + ReactNative (dans un second temps)

Prochaines étapes

Comme précédemment décrit, je vais faire tout mon possible pour vous retranscrire mon parcours du combattant. Mais à cette étape du projet, je suis intéressé d’avoir des beta testeurs qui ont des idées/suggestions à proposer.

Jour #1 : Conception

Une journée sans ouvrir mon éditeur de texte c’est l’objectif que je me suis fixé. J’ai déjà réalisé des mini projets qui avaient été attaqués trop tôt sous un aspect technique. Au détriment de la conception et de l’expérience utilisateur. Aujourd’hui, l’idée était de récupérer un maximum de feedbacks de la part de mes camarades de classe. Cet exercice est obligatoire et vous évite à coup sûr des erreurs bien plus difficiles à rattraper par la suite. Grâce à cette première étape, et à plusieurs interviews dispensés au préalable, j’ai pu affiner quelques détails, notamment sur le parcours utilisateur.

Quand demander telle ou telle information ?

Que faire si l’utilisateur ne souhaite pas donner ses informations ? Son quizz ?

Pour le reste de la journée, je me suis seulement attelé à dessiner mes wireframes. Mais soyons honnête, je vais m’inspirer très fortement de l’application desktop de Tinder.

tinder desktop
Pas la peine de réinventer la roue :)

La seule grande différence résidera donc au like qui enverra vers un formulaire édité par l’utilisateur « swipé ».

Schéma de données

Ce fût de loin la tâche la plus complexe de ma journée. En effet, la schématisation de vos données peut vous faire gagner beaucoup de temps, ou vous en faire perdre beaucoup par la suite.

Voici donc les 4 principaux modèles qui devraient me permettre de faire tourner mon application :

  • User : où seront recensées les id, la bio, les photos etc…
  • Quizz : ce modèle étant relié à l’utilisateur
  • Match : qui représentera la réussite d’un questionnaire, avec ses réponses et les 2 user id concernés
  • Conversation : le modèle qui acceptera tous les messages échangés

Ce dernier étant généré lorsque le modèle Match passera pending à granted (deuxième utilisateur validant la mise en relation).

N’hésitez pas à cette étape du projet de sortir votre stylo et votre feuille de papier.   

Gagner du temps

Pour faciliter la tâche lors de l’élaboration du questionnaire, je souhaite connecter plusieurs API afin de :

  • Proposer un choix exhaustif
  • Sanitizer mes données
  • Construire plus rapidement des QCM car les questions ouvertes sont, dans un premier temps, difficiles à gérer

J’ai donc pris la peine de créer une Google Spreadsheet avec tous mes logins, mot de passes, clés API et documentations associées.

Repo

L’appel du clavier. J’ai pas pu résister à écrire quelques lignes. Ou plutôt exécuter quelques lignes de commande pour générer mon application. Pour ce faire, voici les lignes de commande à taper depuis un dossier commun.

$ express server
$ cd server
$ npm install
$ npm start
$ cd ..
$ vue create client
$ cd client
$ npm install
$ npm run serve

Pour express pas besoin de views. Vous pouvez nettoyer votre dossier. Au niveau de vuejs, il suffit de rajouter vue router et la vie est belle.

express-setup vuejs-setupJe vérifie que sur les ports 3000 et 8080 mes deux environnements fonctionnent.

Même si c’est pas tout à fait ça, voici à quoi devrait ressembler approximativement votre application après ce setup.

Plus ou moins…

Jour #2 : Modèles & Signup

On commence à rentrer dans le vif du sujet. L’objectif du jour était de :

  • Créer mes modèles grâce à Mongoose
  • Générer des seeds (données fausses basées sur le schéma)
  • Monter un sign-up via Facebook

L’objectif est atteint, non sans peine, mais tout est prêt pour démarrer l’application côté base de données.

Modèles & Seeds

Je vais pas détailler ici mes 4 modèles mais plutôt un seul, le modèle User.

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const userSchema = new Schema({
  facebookId: {
    type: String,
    required: true
  },
  status: {
    type: String,
    required: true,
    default: 'pending',
    enum: ['pending', 'granted', 'killed']
  },
  gender: {
    type: String,
    required: true,
    enum: ['1', '2']
  },
  lookingFor: {
    type: String,
    enum: ['1', '2']
  },
  firstName: {
    type: String,
    required: true,
  },
  age: {
    type: Number,
    required: true,
    min: 18,
    max: 99,
  },
  bio: {
    type: String,
    maxlength: 280
  },
  work: {
    type: String,
    maxlength: 70,
  },
  mail: {
    type: String,
  },
  phone: {
    type: String,
    minlength: 10,
    maxlength: 12
  },
  photos: {
    type: String,
  },
  createdAt: {
    type: String,
    default: new Date(),
  },
  updatedAt: {
    type: String,
    default: new Date(),
  }
});

const User = mongoose.model('User', userSchema);
module.exports = User;

Ce modèle est classique mais reprend tous les champs nécessaires pour la suite (enfin, je crois).

Je pense qu’il est cependant important de garder des traces des créations, modifications (cf createdAt & updatedAt).

Le gender et le looking for me permettant de gérer par la suite les différentes orientations sexuelles.

Pour vérifier que tout fonctionne, l’idée est de créer un seed pour bien vérifier que mon application envoie les données souhaitées dans ma base de données (MongoDB). Pour ce faire, voici un script d’exemple :

const mongoose = require('mongoose');
mongoose.connect(process.env.MONGODB_URI);
const User = require('../../models/user.js');

let userDatas = [
  {
    facebookId: '123456789',
    status: 'pending',
    gender: '1',
    lookingFor: '2',
    firstName: 'Vivian',
    age: 29,
    bio: 'Lorem ipsum dolor sit amet',
    work: 'Student @Ironhack',
    mail: 'yolo@yolo.com',
    phone: '0667721671',
    photos: 'https://lh3.googleusercontent.com/-QRfzdXqbRk0/AAAAAAAAAAI/AAAAAAAARKU/0mVuCX8pVhM/s60-p-rw-no/photo.jpg',
  }
]

User.create(userDatas, (err, user) => {
  if (err) {
    throw err;
  }
  else {
    user.forEach(user => {
      console.log(user);
    });
  }
  mongoose.connection.close();
});

TA-DA ! Ça fonctionne !

Le plus dur c’est de faire le premier, après le reste ça roule. C’est une partie qui peut paraître anodine mais pourtant essentielle.

Signup

Bon là par contre, c’est un peu l’enfer. Pour avoir discuté avec plusieurs développeurs, plus ou moins chevronnés, le sign-up / login est toujours une plaie à coder. Même si il est vrai que des initiatives comme Passport ou JWT vous change la vie, ça reste une étape fastidieuse.

Pour mon application, j’ai pris le parti de ne permettre uniquement le login via Facebook. C’était un choix que nous avions fait à l’époque pour le projet MyBetFriend et nous n’avions pas eu à l’époque de retours négatifs. De plus, la quasi totalité des applications de rencontre ont déjà évangélisé cette manière de s’inscrire.

Pour récupérer :

  • Mail
  • Prénom
  • Genre
  • Photos
  • etc…

Facebook fonctionne à la perfection :)

Le conseil que j’aurais à donner pour cette partie, c’est de prendre le temps de créer (avec d’autres développeurs éventuellement) un boilerplate qui sera réutilisé à l’avenir.

Jour #3 : Préparation de l’API

Journée de transition. En ce troisième jour, je ne fus pas à 100% sur le développement de mon application. Cependant, à cette étape du projet, un travail considérable a pointé le bout de son nez : la réalisation de mon API REST.

Cette API a pour vocation de faire communiquer ma partie client (vuejs) avec mon serveur (express).

J’ai pu d’ores et déjà constaté une erreur sur mon signup. En effet, j’ai réalisé ce dernier côté serveur alors qu’il aurait été plus productif de le réaliser côté client d’entrée. Mais bon c’est en faisant qu’on apprend de ses erreurs non ?

Signup & données

Je me suis donc attaché aujourd’hui à transférer mon signup sur ma partie client et a commencé la préparation de mon API. J’ai pu également améliorer la phase d’inscription en faisant matcher les données Facebook avec mon modèle de données. Grâce à cela, je peux dorénavant faire correspondre le prénom de l’utilisateur sur Facebook avec mon modèle de données.

Je pensais (naïvement) qu’il allait être aisé de rapatrier les photos d’un profil sur mon modèle mais ce thread ouvert sur Stackoverflow m’a quelque peu refroidi.

Il faut dorénavant fournir un screencast de son application à Facebook pour avoir la possibilité de récupérer les photos de profil.

Je vais donc devoir attendre d’avoir une application un peu plus précise pour pouvoir soumettre ma review.

Timestamps

Mais j’ai découvert une astuce relativement intéressante sur Mongoose qui me va me permettre de récupérer mes timestamps lors des créations et des modifications de mes données utilisateurs.

Le tout de manière très simple en rajoutant en second argument de mon modèle :

{
  timestamps: true
}

Ce qui donne en sortie :

J’ai également mis à jour mon modèle en remplaçant les 1 et 2 par male et female.

API

Pour en revenir sur l’API, l’idée est d’écrire côté client un fichier api.js qui va interroger mon serveur. Pour protéger ces routes, je vais utiliser mon token généré au signup.

J’utiliserai donc ici le module axios pour me faciliter la vie.

import axios from 'axios'

const mtmt = axios.create({
  baseURL: process.env.API_URL || 'http://localhost:3000/',
});

Demain c’est donc un gros chantier qui m’attend, la réalisation des premières méthodes de mon API pour récupérer toutes les datas nécessaires côté client.

Jour #4 : API & Vuejs – Tome I

Si Google est ton ami, Postman est ton meilleur ami. Surtout quand tu commences à écrire ta première API REST. Effectivement, gérer une application de A à Z commence à devenir complexe. Gérer 4 environnements (front, api, serveur et db) et les faire communiquer entre eux n’est pas plus chose aisée. Surtout lorsque vous commencez à rencontrer des problèmes de type CORS.

CORS

Cross-Origin Resource Sharing… Vous ne connaissiez pas cette acronyme ? Vous en avez de la chance. Le cross origin c’est ce qui va permettre de faire discuter votre front (qui tourne chez moi sur un localhost:8080) avec votre serveur (localhost:3000). Dans un soucis de sécurité, votre navigateur n’accepte pas aisément ce va et vient incessant entre ces deux origines. Heureusement qu’il existe une extension Chrome pour gérer ce genre de soucis.

Ne pas oublier que sur des sites comme Facebook ou encore Github le comportement est parfois hasardeux si l’extension est activée.

Node –inspect

Aka la commande qui te sauve la vie ! Effectuer des console.log(‘tutu’) côté client ça va, mais côté serveur on fait comment pour se déboguer ? Heureusement que cette commande existe et qu’elle vous permet d’ouvrir une interface ad hoc pour pouvoir insérer des points d’arrêts dans votre code côté serveur.

Signup

Encore et toujours la même histoire…

Bon, ils sont bien gentils Facebook, mais réaliser un sign-up correct avec eux c’est quand même pas si évident. Je pense que la prochaine fois ça va partir sur du Firebase direct !

En clair, voici le nouveau chemin pour faire fonctionner tout ce beau monde :

  1. Front : clique sur le sign-up
  2. Facebook : retourne les informations dans mon serveur (id, firstName…)
  3. Serveur : envoie le token et les informations de Facebook via un redirect
  4. Front : utilise les req.params pour faire tourner l’application
  5. Il y’a pas de 5, ça suffit.

Vuejs, les prémices

Sur les conseils de mes professeurs émérites, il est de bon ton de développer le front et l’api en même temps, afin de cadrer au mieux avec les desiderata des futurs utilisateurs. C’est donc ainsi que j’ai commencé à faire avancer mon front.

Je saluerai donc jamais assez les personnes qui vont vivre les repos comme Buefy ou Element. Ces modules permettent de réaliser des composants à la vitesse de l’éclair et ça c’est cool.

 

Par exemple, pour proposer un range d’âge sur mon application, voici le composant récupérer sur Element :

Maintenant que mon sign up est en place, il me reste plus qu’à attaquer ma fonctionnalité quizz qui ne sera pas une mince affaire non plus.

Jour #5 : API & Vuejs – Tome II

‘Va y’en avoir combien des tomes ?!?

Il me reste 9 jours de code et j’ai l’impression que j’avance pas. Je veux pas sortir les violons, mais quand même, ce n’est pas chose aisée. Surtout quand votre IDE (Visual Code) décide de péter un plomb. 2 heures de perdues, merci.

Spotify

Le gros morceau de la journée fût de connecter l’API de Spotify à mon modèle de Quizz. Lors du sign-up je demande à l’utilisateur quel est son groupe préféré.

C’était assez chronophage car je devais récupérer le code, puis le token mais bon c’est très instructif. Autre avantage, je vais pouvoir dupliquer sur mes autres API rapidement ce week-end.

En parallèle de ça, j’apprends aussi React (qui est probablement un peu plus complexe pour un débutant). Je veux pas rentrer dans une guéguerre stérile sur les différents frameworks javascript, mais il faut reconnaître que Vuejs à quelques avantages vis à vis de React.

Syntactic sugar

Vuejs est assez facile à lire et à écrire. Par exemple, pour ma génération d’artistes, voici ce que j’ai pu faire :

<figure class="image is-4by3">
  <img v-if="artist.images[0]" v-bind:src=artist.images[0].url alt="Placeholder image">
  <img v-else src="https://placehold.it/600x600" alt="Placeholder image">
</figure>

Spotify n’a pas d’image pour tout ses artistes. Et si une image manque, c’est toute la requête qui tombe à l’eau. Grâce à Vuejs, en 2 lignes de code, vous pouvez vous prémunir de ce genre de comportement. Et ça c’est cool.

T’as la photo c’est bien, tu l’as pas, placehold.it fera le reste !

Jour #6 : API & Vuejs – Tome III

Autre avantage, je vais pouvoir dupliquer sur mes autres API rapidement ce week-end.

Rien.

N’est.

Rapide.

Je devrais le  savoir quand même ! Il est vrai que j’ai pu transposer ma recherche de musique sur les films relativement rapidement. L’API de TMDB est super bien faite et il existe de nombreux wrappers sur GitHub.

Mais en partageant mon projet à une amie, elle m’a fait une remarque pertinente.

Non mais c’est bien gentil les musiques, les films, mais le trait de caractère c’est quand ?

Spafo. Du coup, j’ai mis de côté les intégrations API pour partir sur un autocomplete très simple : qualité & défaut.

Autocomplete

Quelle joie ce Buefy. Vous pouvez facilement trouver votre bonheur dans la partie Forms Controls.

Source : https://buefy.github.io/#/documentation/autocomplete

<template>
    <section>
        <p class="content"><b>Selected:</b> {{ selected }}</p>
        <b-field label="Find a JS framework">
            <b-autocomplete
                rounded
                v-model="name"
                :data="filteredDataArray"
                placeholder="e.g. jQuery"
                icon="magnify"
                @select="option => selected = option">
                <template slot="empty">No results found</template>
            </b-autocomplete>
        </b-field>
    </section>
</template>

<script>
    export default {
        data() {
            return {
                data: [
                    'Angular',
                    'Angular 2',
                    'Aurelia',
                    'Backbone',
                    'Ember',
                    'jQuery',
                    'Meteor',
                    'Node.js',
                    'Polymer',
                    'React',
                    'RxJS',
                    'Vue.js'
                ],
                name: '',
                selected: null
            }
        },
        computed: {
            filteredDataArray() {
                return this.data.filter((option) => {
                    return option
                        .toString()
                        .toLowerCase()
                        .indexOf(this.name.toLowerCase()) >= 0
                })
            }
        }
    }
</script>

Comme vous le remarquerez, même la partie .js est gérée. Terminé bonsoir.

Demain petite pause, je vais intégrer la landing page et lâcher un peu le duo infernal Express / Mongoose.

Jour #7 : Landing Page

Petit dimanche détente, intégration de ma landing page. OKLM.

Mon premier jet est disponible ici.

Étant donné qu’il faudra fournir une landing page de notre projet, autant le faire maintenant. Je pense que je serai tellement emmerdé par ma mise en production plus tard…

Mais ce n’est pas une excuse pour faire une landing page moisie. J’ai souhaité incorporer de la parallaxe et quelques animations CSS. Pour ce faire j’ai utilisé deux ressources très intéressantes : paroller & animista.

Paroller

Source : https://github.com/tgomilar/paroller.js/

Paroller est un plugin basé sur jQuery qui permet des animations parallaxes très facilement. Alors oui je sais, utiliser jQuery c’est le mal gnia gnia… Mais bon, ça marche, c’est facile, pas la peine de perdre des heures à reproduire la même chose avec du Tween non ?

Ce que j’ai le plus apprécié dans paroller c’est sa facilité de mise en place. Il suffit de déclarer une classe sur la partie qu’on souhaite animer et la suite se gère très bien :

$(".p1, [data-paroller-factor]").paroller({
  factor: 1,              // multiplier for scrolling speed and offset
  type: 'foreground',     // background, foreground
  direction: 'horizontal' // vertical, horizontal
});

Il suffit de gérer ces 3 paramètres et le tour est joué.

Animista

Source : http://animista.net/

Animista c’est le Google des animations css. Il suffit de piocher son animation, copier coller sa classe, ses keyframes et ça marche.

Jour #8 : De la data

Journée relativement productive. Mise à jour du Trello, finalisation du quizz. J’attaque maintenant le gros morceau : l’interface de mise en relation (swipe + quizz + chat). Mais avant cela, deux travaux relativement importants : enregistrer l’utilisateur localement (local storage) et création de faux profils.

Ce n’est pas pour faire semblant d’avoir une croissance exponentielle, non c’est plutôt pour tester tous les cas de figures. Les combinaisons possibles de recherches sont très élevées (âge, âge recherché, sexe et orientation sexuelle).

Enregistrer l’utilisateur localement

J’avais mis ça de côté en pensant que c’était pas trop compliqué à faire par la suite. C’est le cas, mais autant le faire de suite la prochaine fois :)

data: function() {
    return {
      error: null,
      files: [],
      photos: '',
      id: this.$route.query.id,
      firstName: this.$route.query.firstName
    }
  }

Au sign-up, je récupère l’id depuis l’url de callback de Facebook.

Une fois présenté, je suis en mesure de l’envoyer, avec axios, dans mon local storage (developer tools > application > local storage).

NB : j’envoie aussi mon token mais pas au même endroit :)

.then( res => {
        const { data } = res;
        localStorage.setItem('id', obj._id);
        axios.defaults.headers.common['Authorization'] = 'Bearer ' + data.token;
        return data;
      })

C’est pas les lignes de code de l’année mais ça fait le taf.

Par la suite, je récupère facilement l’id comme suit :

        .sendTreshold({
          userId: localStorage.getItem('id'),                
          treshold: this.treshold
        })

Faker.js

La trouvaille. Je pensais devoir scrapper des sites de rencontre pour pouvoir avoir une première base de test. Mais bon, comme vous devez le savoir, le scrapping, c’est pas bien.

Heureusement je suis tombé sur Faker qui est une librairie permettant de générer des quantités phénoménales de données. L’un des énormes avantages, c’est que Faker est capable de rester fidèle à la localité. Ce qui permet, dans mon cas, de mettre uniquement des personnes françaises.

const mongoose = require('mongoose');
mongoose.connect(process.env.MONGODB_URI || "mongodb://localhost/mtmt");
const User = require('../../models/user.js');

var faker = require('faker');
faker.locale = "fr";

var file = [];
for (let i = 0; i < 2000; i++) {
  
  let fakeDatas = {
    facebookId: faker.random.number(),
    status: 'granted',
    gender: faker.random.arrayElement(['male', 'female']),
    lookingForGender: faker.random.arrayElement(['male', 'female']),
    lookingForRange: [{'min' : faker.random.number({min:18, max:24}), 'max' : faker.random.number({min:32, max:49})}],
    firstName: faker.name.firstName(),
    age: faker.random.number({min:18, max:49}),
    bio: 'Je suis un faux compte et je le vis bien.',
    work: faker.company.companyName(),
    mail: faker.internet.exampleEmail(),
    phone: faker.phone.phoneNumber(),
    photos: faker.image.avatar(),
  }
  file.push(fakeDatas)
}

User.create(file, (err, user) => {
  if (err) {
    throw err;
  } else {
    user.forEach(user => {
      console.log(user);
    });
  }
  mongoose.connection.close();
});

Extrait :

{ facebookId: '37981',
  status: 'granted',
  gender: 'male',
  lookingForGender: 'female',
  lookingForRange: [ { min: 22, max: 46, _id: 5a9e51b9c932da671f9b1c2b } ],
  firstName: 'Lena',
  age: 48,
  bio: 'Je suis un faux compte et je le vis bien.',
  mail: 'Pauline90@example.net',
  phone: '0689125768',
  photos: 
   [ 'https://s3.amazonaws.com/uifaces/faces/twitter/nfedoroff/128.jpg' ],
  swiped: [],
  _id: 5a9e51b9c932da671f9b1c2c,
  createdAt: 2018-03-06T08:30:49.843Z,
  updatedAt: 2018-03-06T08:30:49.843Z,
  __v: 0 }
{ facebookId: '74494',
  status: 'granted',
  gender: 'male',
  lookingForGender: 'female',
  lookingForRange: [ { min: 19, max: 45, _id: 5a9e51b9c932da671f9b1c2d } ],
  firstName: 'Célia',
  age: 41,
  bio: 'Je suis un faux compte et je le vis bien.',
  mail: 'Lo_Leroux@example.com',
  phone: '+33 614805908',
  photos: 
   [ 'https://s3.amazonaws.com/uifaces/faces/twitter/kianoshp/128.jpg' ],
  swiped: [],
  _id: 5a9e51b9c932da671f9b1c2e,
  createdAt: 2018-03-06T08:30:49.843Z,
  updatedAt: 2018-03-06T08:30:49.843Z,
  __v: 0 }

La vie est belle.

Jour #9 : Vuejs et ses composants

J’ai pu goûter aujourd’hui à la puissance de  Vuejs. Autre force de ce framework c’est la structuration de ses composants et de ses vues.

Pour mon interface de swiper j’ai donc un composant Card et un autre Quizz. Ces deux composants se retrouvant dans une vue Swiper.

  1. Swiper.vue – view
  2. Card.vue – component
  3. Quizz.vue – component

De base, le quizz est désactivé. Je l’active sur le click Like sur la Card.vue. Mais je le referme depuis le composant Quizz.vue grâce à un event : $this.emit(‘hide’)

Ce dernier est récupéré dans Card.vue avec @hide=hideQuizz

Plutôt facile non ?

Dernière petite astuce, utiliser beforeMount() pour charger l’API avant le composant dans le but d’afficher de la data dès que le composant prend vie.

Jour #10 : Like & Dislike + Heroku

Je dois présenter mon projet vendredi. Ça serait pas mal de faire les fonctionnalités annoncées non ? Avec un petit déploiement également ?

Aujourd’hui je me suis donc attaché à coder mes features clés qui Like & Dislike l’utilisateur avec une première mise en production pour pas avoir trop mal vendredi matin.

De toutes façons on fait jamais une MEP un vendredi… Source

Like & Dislike : MongoDB & Vuejs

Pour que l’application cadre avec le souhait de l’utilisateur, il est impérieux de proposer des profils qui cadrent avec le sexe, l’orientation sexuelle et l’âge.

Pour ce faire…

Ma route

router.get('/api/getmatches/:id', function (req, res, next) {
  User.findById(req.params.id, function (err, user) {
    if (err) {
      next (err);
    } else {
      User
      .find({
        gender: user.lookingForGender,
        age: { $gte : user.lookingForRange.min, $lte: user.lookingForRange.max } 
      })
      .limit(100)
      .exec((err, users) => {
        if (err) {
          next(err);
        } else {
          res.json(users)
        }
      })
    }
  })
})

Qui sera améliorée demain bien entendu…

Comme vous le voyez, rien de très compliqué. En fonction de l’id de l’utilisateur, je récupère les informations nécessaires pour lui proposer les matches qui correspondent à ses envies.

Par la suite, je requête la base en entier sur ses critères. Je limite à 100 dans un premier temps, pas besoin de plus pour tester.

Mes méthodes

methods: {
    getMatches() {
      api
        .getMatches(localStorage.getItem("id"))
        .then((users) => {
          this.users = users
        })
        .catch(err => {
          this.error = err;
        })
    },
    increment(){
      this.counter++;
    }
  },
  beforeMount() {
    this.getMatches()
  },

Sur Vuejs il faut conceptualiser plusieurs choses.

L’appel de l’API se fait bien sur la base de l’id de l’utilisateur. C’est donc tout naturel de le récupérer depuis le local storage. 

Ce que j’utilise en revanche c’est une incrémentation pour faire passer les profils les uns après les autres. Il serait peut être intéressant que je filtre l’objet en sortie sur la date d’inscription, pour faire passer en avant les anciens profils. À voir.

Ne pas oublier le beforeMount() et on est bons.

Heroku

Mouairf… Pas très glorieux tout ça. Le déploiement est à mon sens une tâche réellement ingrate. Très difficile à déboguer, vous pouvez passer un temps considérable pour un résultat faible. Bon, il est vrai que vous pourrez toujours crâner auprès de vos petits copains en fin de journée.

Trève de plaisanteries, Heroku est quand même bien pratique et très bien documenté. En plus c’est gratuit.

Jour #11 & #12 : Fin.

Pour les derniers jours impossible de prendre le temps d’écrire. Sur la journée #11 j’ai réalisé pas moins de 20 commits sur mon application. Record battu :)

Quizz

Sur cette journée j’ai tout simplement réussi à mettre en place ma fonctionnalité principale : le quizz.

La plus grande complexité fût de réaliser des faux quizz et des les lier aux faux utilisateurs.

const mongoose = require("mongoose");
mongoose.connect(process.env.MONGODB_URI || "mongodb://localhost/mtmt");
const Quizz = require("../../models/quizz.js");
const User = require("../../models/user.js");

var faker = require("faker");
var randomArtists = require("./random/randomArtists");
var randomMovies = require("./random/randomMovies");
var quality = require("./random/quality");
var defect = require("./random/defect");

var users = [];
User.find({})
    .select({
        _id: 1
    })
    .limit(100)
    .exec((err, users) => {
        if (err) {
            next(err);
        } else {
            var file = [];
            for (let i = 0; i < 20000; i++) {
                let fakeDatas = {
                    userId: faker.random.arrayElement(users),
                    treshold: faker.random.number({ min: 0, max: 100 }),
                    music: {
                        answer: faker.random.arrayElement(randomArtists),
                        badResponses: [
                            faker.random.arrayElement(randomArtists),
                            faker.random.arrayElement(randomArtists),
                            faker.random.arrayElement(randomArtists)
                        ]
                    },
                    movie: {
                        answer: faker.random.arrayElement(randomMovies),
                        badResponses: [
                            faker.random.arrayElement(randomMovies),
                            faker.random.arrayElement(randomMovies),
                            faker.random.arrayElement(randomMovies)
                        ]
                    },
                    traits: {
                        "quality.answer": faker.random.arrayElement(quality),
                        "quality.badResponses": [
                            faker.random.arrayElement(quality),
                            faker.random.arrayElement(quality),
                            faker.random.arrayElement(quality)
                        ],
                        "defect.answer": faker.random.arrayElement(defect),
                        "defect.badResponses": [
                            faker.random.arrayElement(defect),
                            faker.random.arrayElement(defect),
                            faker.random.arrayElement(defect)
                        ]
                    }
                };
                file.push(fakeDatas);
            }

            Quizz.create(file, (err, quizz) => {
                if (err) {
                    throw err;
                } else {
                    quizz.forEach(quizz => {
                        console.log(quizz);
                    });
                }
                mongoose.connection.close();
            });
        }
    });

Pour ce faire j’utilise toujours ce bon vieux Faker.js qui fait gagner un temps considérable. Une fois le fichier créé je le pousse en base via Mongoose.

Refacto

Sur la doc de React j’ai trouvé une partie très intéressante : Thinking In React. Je n’ai pas (encore) trouvé son pendant côté Vuejs.

Cette partie  vous explique comment découper une petite application web en composants. C’est très intéressant, car si vous commencez à créer une application avec une architecture bancale, la moindre fonctionnalité va devenir très compliquée à produire.

C’est en ce sens que j’ai souhaité (la veille de mon rendu) « refactoriser » mon interface de swipe.

Ce n’est pas un choix que je regrette car j’ai pu avancer beaucoup plus vite par la suite. Je pense que pour la prochaine application, je vais utiliser beaucoup plus de papier et de feuilles blanches pour conceptualiser l’application.

Toasts

Petite fonctionnalité intéressante, qui plus est pour l’utilisateur final, le toast. C’est d’une facilité enfantine à mettre en place et le résultat est plutôt sympa pour l’utilisateur.

          .then(data => {
            this.$toast.open({
              message: "Bien reçu",
              type: "is-success"
            });
            this.$router.push("/quizz-info");
          })

Vous pouvez rajouter rapidement dans votre retour de données API ce petit bout de code qui avertira l’utilisateur que tout est OK. Le tout avant de le rediriger vers la prochaine page.

It’s a match!

Pour les besoins de la démonstration live, j’ai du mettre insérer un pattern fixe sur les bonnes réponses. J’aurais bien entendu pas fait ça comme ça pour une vraie mise en production. Mais bon j’ai codé ça en quatrième vitesse et ça faisait le taf, donc bon…

router.post("/api/postquizz/", function(req, res, next) {
    Quizz.findById(req.body._id, function(err, quizz) {
        if (err) {
            next(err);
        } else {
            var score = 0;
            if (req.body.musicAnswer === "A") {
                score = 25;
            }
            if (req.body.movieAnswer === "B") {
                score += 25;
            }
            if (req.body.qualityAnswer === "C") {
                score += 25;
            }
            if (req.body.defectAnswer === "A") {
                score += 25;
            }
            if (score > quizz.treshold) {
                Match.create({
                    _quizzId: req.body._id,
                    _userRequester: req.body._userRequester,
                    _userCandidate: req.body._userCandidate,
                    average: score / 100
                });
                res.json({
                    message: "BRAVO"
                });
            } else {
                res.json({
                    message: "NOPE"
                });
            }
        }
    });
});

npm run build

Autre élément important appris lors de ces folles journées du code, l’intérêt de faire passer un build de production assez rapidement. En effet, Vue (et les autres) vont compiler votre code et le distribuer dans un dossier /dist. Le seul petit soucis, c’est que si vous avez fait le barbare comme moi en bougeant des classes css natives vous allez retrouver votre appli tout en désordre. Donc ce qui peut être pas mal c’est de faire un build en fin de journée pour bien vérifier que tout est à sa place.

Ou sinon vous codez correctement et vous faîtes des classes partout.

Conclusion

Voila. http://mtmt.viviansarazin.com/

NB : L’application n’est pas optimale en version mobile

Deux semaines de code, une application. Je pense que la prochaine fois je pourrais faire la même application en une semaine. Mais bon il faut passer par là !

Rétrospectivement, je dirais que j’aurais pu passer un peu plus de temps sur la phase de conception afin de mieux préparer mon API, mes composants toussa toussa.

J’ai aussi perdu pas mal de temps sur le setup, plus précisément sur le signup via Facebook. La prochaine fois je pense que je partirais directement sur du Firebase. Autre possibilité, réaliser un boilerplate MEVN pour gagner du temps.

Remerciements

C’est le moment de sortir les mouchoirs. Faut bien que ça s’arrête quand même !

Pour les profs : Merci Eduardo, Guillaume, Maxence, Mickaël A, Mickaël B, Nizar & Yacine.

Et les autres : Merci Antoine, Charlotte, Karim & Maya.

 

Bien à vous :)

Pour vous inscrire à la newsletter c’est par ici :

Maîtrise tes datas dès le premier jour

Le growth-hacking sans datas c’est un peu comme jouer au foot sans ballon : c’est nul. Le growth-hacker vit une relation pour le moins particulière avec la donnée.

« Mes actions auront elles l’impact escompté ? »

« Pourquoi ça chute ici ? »

Tout growth-hacker se sera posé au moins une fois dans la journée des questions analogues.

Mais ne l’oublions pas, un growth-hacker est avant tout conscient de la puissance des processus bien huilés. Les outils arrivent ensuite.

Et c’est l’objectif de cet article : partager toutes les connaissances nécessaires pour mettre en place, dès le premier jour, un processus pour extraire et interpréter de manière sûre vos données. Les outils proposés ici sont uniquement gratuits. Ce ne sont pas forcément les plus performants sur le marché, pour un premier environnement data, ça devrait être suffisant.

Dans une première étape nous allons parler de Google Tag Manager qui est un gestionnaire de balises. C’est ici que nous incorporerons par la suite les différentes balises. En termes d’Analytics nous parcourrons Google Analytics & Mixpanel pour enfin terminer sur l’édition de dashboards via Google Data Studio.

Le lien vers l’infographie

Google Tag Manager

– Kevin* tu peux me mettre ce petit script dans le <head> du site s’il te plaît ?

– Non.

– Ok merci, t’es super !

On a tous eu ce genre d’échange avec son développeur (oui, beaucoup de bon dév’ s’appellent Kevin, c’est comme ça). En réalité si votre développeur ne daigne pas insérer votre misérable script vous n’allez pas pouvoir faire grand-chose.

Il vous reste une seule solution : le conjurer à genoux d’accéder à votre requête.

C’est ainsi que Google, dans sa grâce la plus aboutie, a proposé au monde de l’Internet : Google Tag Manager. GTM permet, en insérant deux petits scripts dans votre application, de piloter l’intégralité de vos balises. Ainsi vous n’aurez qu’à faire insérer dès le début de votre collaboration ces fameux scripts GTM et vous pourrez ajouter, modifier supprimer vos scripts secondaires depuis l’interface.

Fini les passes d’armes avec Kevin. Pfiou !

 

Mais GTM a d’autres côtés tout aussi pratiques.

Si vous voulez en savoir plus sur l’installation vous pouvez vous renseigner sur la documentation officielle : https://developers.google.com/tag-manager/quickstart

Variables

GTM identifie vos variables et vous permet de les communiquer entre différents services.

Par exemple, si votre formulaire renvoie first_name, last_name & email, vous allez pouvoir pousser ces informations à d’autres services tiers.

C’est très simple à réaliser et leur interface de débogage (mon Dieu quel mot affreux…) est vraiment optimale pour vérifier votre Data Layer (données envoyées à GTM).

Environnement

Cette fonctionnalité est vraiment intéressante car elle vous permet de découper votre écosystème en différents modules.

Imaginons que vous ayez :

  • Blog
  • Landing page (x4)
  • Site Web
  • Application

Vous allez pouvoir aisément définir quelles balises déclencher selon les environnements identifiés.

Exemple : sur votre Front pas besoin d’analytics poussé (dans un premier temps) l’usage de KissmetricsMixpanel ou Amplitude serait plus utile sur votre application.

Ainsi vous n’ajoutez pas tout, partout. Ceci vous permettant d’éviter lourdeurs dans le code et surtout des « dépenses » inutiles.

Si vous souhaitez aller plus loin je vous conseille de lire les ressources fournies par Segment  qui est une alternative plus que sérieuse à GTM. Si maintenant vous voulez voir ce qu’on peut faire quand on maîtrise à la perfection sa data regardez du côté de chez hull.io. Indécent.

Analytics

Maintenant que votre Google Tag Manager est en place dans tous vos modules (blog, appli, front etc…), vous allez pouvoir insérer vos analytics. Que la fête commence !

Tracking Plan

Pour que votre environnement soit clair et maintenable, je ne peux que vous conseiller de réaliser un Tracking Plan avec une nomenclature précise.

Pour vous aider, j’ai réalisé une spreadsheet qui comprend 3 onglets.

  1. Questions : L’idée est de pouvoir croiser vos différents modules et les outils d’analyses associés. Qu’est-ce qui est réalisable ? Quels sont mes KPI’s ?
  2. Tracking Plan : Une fois les bonnes questions posées, il vous sera plus aisé de réaliser un tracking plan. Diana Smith de Segment nous résume tout ça.diana h. smith @dianahsmith Tracking Plan. Name Why Properties Location Signed Up Key event for user interest, marketing c...
  3. Nomenclature : Pour que vous puissiez mettre en œuvre votre Tracking Plan il vous faudra nommer vos événements correctement.

Google Analytics

Google nous gratifie une fois de plus d’un bel outil : Google Analytics. Très utile pour identifier des données comme :

  • Source
  • Support
  • Taux de rebond
  • Conversions
  • etc…

Google Analytics devient d’un coup beaucoup moins performant lorsqu’il s’agit de faire de l’analytics user-centric. Il reste néanmoins excellent pour tous les aspects « marketing ».

En effet, Google Analytics fonctionne à la page view alors que d’autres analytics s’attachent à calculer sur l’event.

C’est ainsi que Google Analytics n’est pas le meilleur outil à utiliser pour tous les aspects funnels et autres cohortes de rétention.

Mixpanel

Quand on parle d’analytics user-centric Mixpanel n’est effectivement jamais très loin. Mixpanel est globalement très performant et vous permet d’effectuer dorénavant votre tracking sans recourir à votre Kevin local.

NB : je rédige une MAJ avec Amplitude dans pas longtemps.

Autotrack

Que ce soit sur une application web ou mobile, la fonctionnalité Autotrack développée par Mixpanel vous permettra de créer vos événements personnalisés.

Il vous suffit juste de cliquer sur votre élément et de lui donner un petit nom.

Probablement le petit nom que vous aurez au préalable défini dans votre nomenclature :p

 

Sélecteurs CSS

Autotrack va prendre en compte votre sélecteur CSS et vous indiquer si il a été cliqué ou non. Toutefois, si Kevin n’a pas inséré des id ou tout simplement changé les classes Bootstrap, Mixpanel va compter tout ceci en doublon.

#jesuisbtnlarge

Pas d’inquiétudes voici une solution qui fera très bien l’affaire.

  1. Ouvrir l’inspecteur

  2. Copier le sélecteur CSS

  3. Coller dans Custom Event

Bonus : Si vous devez fusionner plusieurs éléments rajouter une virgule à la fin de votre sélecteur. Vous pourrez ainsi créer des custom events tout en restant en mode free chez Mixpanel.

Si vous souhaitez aller plus loin avec Mixpanel & Google Tag Manager je vous conseille cette vidéo :

Hotjar & Fullstory

Hotjar & Fullstory ne sont pas des analytics communs. Même si vous y trouverez des funnels, ou des diagrammes circulaires (a.k.a. camembert) leur force principale ne réside pas, à mon sens, dans ces représentations.

Leurs fonctionnalités principales sont l’enregistrement vidéo des parcours de vos visiteurs. Ces analytics très sérieux vous permettront de comprendre ce que fait réellement votre utilisateur.

Ces outils sont à mes yeux inévitables pour toutes personnes travaillant de près ou de loin dans l’UX.

Grâce à GTM vous allez pouvoir déclencher par exemple Hotjar sur votre Home et Fullstory sur votre App très facilement et ainsi économiser vos crédits freemium.

Dashboards & reportings

Votre écosystème est en place, vos tracking ne laissent rien passer, la vie est belle. Mais il manque encore quelque chose pour être au summum du kif : la génération de vos dashboards et autres reportings.

Google Spreadsheet

J’ai réalisé une vidéo l’an dernier pour présenter un module complémentaire de Google Spreadsheet qui est plus que pratique.

Le modus operandi est le suivant :

  1. Création de vos requêtes

  2. Planification

  3. Extraction des données

  4. Tableaux croisés dynamiques

  5. Représentation graphique

Avec ça vous n’avez plus à vous soucier de l’actualisation de vos dashboards, Google s’en charge tout seul dans la nuit, comme un grand.

Toutefois attention à ne pas compiler des données échantillonnées dans vos tableaux de bords, ça ferait mauvais genre (En effet, Google Analytics a tendance à échantillonner les datas quand vous faîtes une requête trop importante).

Google Data Studio

Vous avez probablement entendu parler de cette louable initiative de Google de nous fournir encore un outil aussi beau que puissant pour visualiser nos données.

J’ai l’impression que je fais une lettre de motivation à Google…

GDS est très pratique car parfaitement synchronisable avec Google Analytics et aussi et surtout Google Spreadsheet. Grâce à cela vous allez pouvoir rapatrier dans l’interface de visualisation vos données actualisées et calculées.

Dernière fonctionnalité très appréciable, la connexion de bases SQL. Pour que Kevin soit enclin à vous donner les accès, demandez un accès en lecture, ça suffira amplement.

J’ai aussi l’occasion de tester Reeport qui est une alternative plus que solide à Google Data Studio. L’interface est particulièrement fluide et soignée.

Conclusion

La data est votre juge de paix. Sans ces précieuses données vous ne serez pas capables de faire évoluer votre produit.

L’objectif sous-jacent de cet article est donc de vous donner tous les outils, bonnes pratiques, pour que vous déployez dès le premier jour le meilleur système (gratuit) possible. Gagnez du temps et réinvestissez le dans ce qui est probablement le plus important : l’amélioration de votre compréhension utilisateur.

Les features viendront par la suite et Kevin saura quoi coder grâce à vous.

Pour t’inscrire à la newsletter c’est là :

sdk

Comment générer des hacks avec des SDK ?

La joie des stores ! J’en avais entendu parler, mais s’y confronter c’est tellement plus marrant. J’avais bien travaillé sur quelques lancements, sur de l’ASO par le passé, mais rien de comparable à ce que je vais vous présenter. De la conception en passant par ma première panne serveur, je vais tenter de vous décrire notre parcours avec MyBetFriend et vous dire comment nous nous en sommes sorti avec notamment 3 SDK fabuleux.

Concevoir une application ou l’art de perdre 5 ans d’espérance de vie en autant de semaines

Beer & Pitch

Il fallait bien y aller dans le mobile un jour. Oui, il le fallait. J’avais bien eu quelque idées mais rien de quoi constituer une équipe sur un objectif commun. Comme toute idée valable du IIIème millénaire, celle-ci naquit autour d’une pinte de bière avec un ami. Nous regardâmes un match de foot dans un bar miteux de Paris, et soudain éclair !

Parier ma bière auprès de mon ami selon l’issue du match. Tout deux fascinés par les chiffres, nous nous sommes projetés dans l’agrégation des données statistiques TV en live dans cette hypothétique application mobile.

Ça doit déjà exister… Tu penses que ça plaira ? Mouairf… C’est sympa mais bon…

Il fallut se rendre à l’évidence, mon elevator pitch était nul et donnait autant envie que la vision de Margaret Tatcher nue dans la neige (désolé…).

Face à ce premier échec, je décidais d’appeler l’éditeur de statistiques en question et de lui soumettre mon pitch. Grâce à quelques bottes secrètes je réussis à contacter mon interlocuteur 48h après mon premier coup de fil.

Après avoir pitché mon embryon de projet, je n’entendis qu’un silence pesant. Mais cette fois-ci la réponse fût positive. En fait, ce silence marquât mon premier succès, celui d’avoir attirer l’attention et proposé un service novateur auprès d’un professionnel du secteur.

Il faut être bien évidemment lucide, avec mon fournisseur nous allions commencer une relation commerciale aussi. Mais au vu et au su de son soutien indéfectible, je pense que notre alliance allât plus loin qu’une simple relation tarifée.

Les faisabilités techniques et temporelles scellèrent ma joie et firent naître mon optimisme (naïf) d’entrepreneur digital.

Un pour tous et tous pour un #YOLO

Requinqué par ce premier « succès », je fus à même de monter une équipe de 6 personnes. En l’espace de 2 mois nous étions fixé sur un nom, sur un concept, et surtout sur une finalité à donner à ce projet.

Fondamentalement, nous en avons tous marre de ce bullshit continuel «plus qu’une société, une équipe gnia gnia… » mais typiquement comment les start-up peuvent réaliser de superbes projets sans une équipe de rockstar ? Un grand groupe, avec de l’ancienneté, un réseau, une marque connue, peut se traîner des boulets dans son effectif. Une start-up non. En tout cas si elle le fait, elle finira très rapidement dans le cimetière des start-up.

Il existe plus de start-up mortes que de start-up en activité. Click To Tweet

#instantprofond

Pour en revenir à l’équipe, je dirais qu’il faut retrouver en elle tous les caractéristiques qui permettront de réaliser des 1+1=3.

Avec de la contradiction on améliore ses idées, son travail. Je pense que cette notion est tout de même fondamentale si tant est que vous recherchiez un produit qui s’adresse à autre chose qu’une étroite niche.

Et la conception fût…

J’ai pu remarquer que lorsque vous créiez une application ou quand bien même un service innovant, la majorité des personnes ont tendance à entendre ce qu’elles veulent et à devancer votre effort sacré d’imagination. Infâmes cloportes ! Même si vous pouvez avoir de superbes idées qui viennent à la volée, il va vous être impossible d’avancer sur votre projet. Vous allez déployer toutes les features suggérées par tout votre entourage et votre application ne ressemblera plus à rien.

A vouloir plaire à tout le monde, vous ne séduirez personne et même vous vous aurez un certain dégoût pour vous-même par la suite.

C’est à cette étape bien précise qu’il est de bon aloi d’utiliser Canva (ou Balsamiq) & Invision.

Grâce à ce couple de SAAS gratuit, il vous sera possible de réaliser vous même votre prototype d’application et d’itérer dessus sans même à avoir expliquer vos tenants et aboutissants.

L’UX c’est comme une blague, si tu dois l’expliquer c’est que c’est pas bon

A ce petit jeu là je peux vous garantir qu’avec mon équipe on a pas été tout le temps drôle. Loin de là. Mais mauvaises blagues après mauvaise blagues, nous avons pris le parti de simplifier notre service au maximum et surtout de s’en remettre à une chose pour trancher nos décisions : la data.

Toute le monde n’a pas le même humour. Pourtant nous partageons tous, quelques trucs en commun. Par exemple : les cons, l’air que nous respirons, les gamins qui chialent dans le train (j’en ai un à côté de moi que j’ai envie de massacrer là…), les lois de la physique et les mathématiques. Notre avions donc décidé de choisir ce dernier point pour avoir un juge de paix. C’est assez paradoxal car je connais peu de personnes qui exultent à la vue d’une feuille Excel, mais quand bien même, être data-oriented ne vous fera aucun mal si vous lancez une application.

Exemple de blague tentée : le login uniquement par Facebook. Même si ça n’a pas fait marrer tout le monde au départ, il aura gêné, in fine, 13 % de l’ensemble de nos utilisateurs. Et cette métric nous a été remontée par le premier SDK que je vais vous présenter, MixPanel.

Les SDK c’est trop bien !

MixPanel

Ai-je encore besoin de présenter MixPanel ? Oui ? Bon ok…

MixPanel est à l’application mobile ce que Michael Ange est à la renaissance italienne. (Normalement avec une présentation comme ça et un backlink aussi puissant je devrais gagner un peu de datas gratis…).

Mais arrêtons là les conneries, MixPanel est avant tout un SDK d’Analytics gratuit jusqu’à un certain niveau de consommation. De plus votre développeur n’aura aucun mal à intégrer ce SDK sur iOS & Android.

Fonctionnalités

Les fonctionnalités de MixPanel sont multiples et variées. Vous allez être tout d’abord en mesure de garder la trace de tout vos utilisateurs, définir des profils, intégrer leurs tokens pour déboguer et retrouver ainsi rapidement toutes les informations que vous souhaitez remonter.

De plus vous allez être en mesure d’intégrer des funnels de conversions qui vous montreront les différents points de frictions de votre application. A vous de travailler conjointement avec vos designers et développeurs pour éviter toutes chutes. La bonne interprétation des metrics est souvent à l’origine des hacks.

Autre fonctionnalité, les cohortes de rétentions. C’est peut être là que ça commence à vraiment devenir marrant. En effet, réaliser une application c’est cool, la développer c’est marrant mais générer de la rétention c’est générer de l’amour pour elle. On a plaisir à y aller et surtout à y revenir.

C’est là qu’on (en général) monétise et qu’on génère de la marge nette de manière durable. Difficilement ailleurs.

MixPanel présente aussi d’autres fonctionnalités comme l’A/B testing et les notifcations. Mais ça ça vient plus loin…

Alternative à MixPanel, Amplitude SDK suggéré par Alexandre Jubien de Thinkmobile

OneSignal

Le problème avec les notifications c’est qu’elles ont souvent une fâcheuse tendance à vouloir partir toutes en même temps. Et si votre développeur ne prévoit pas une méthode pour les espacer afin d’éviter un pic de charge trop violent, vous allez avoir un nombre incalculable de notifications non délivrées. Qui plus est difficile de dire à la volée combien sont envoyées, cliquées etc.

C’est à ce niveau précis que OneSignal intervient. Cette fois-ci pas besoin de cirage de chaussures, One Signal est entièrement gratuit.

Le SDK est semble-t’il un petit peu plus complexe à intégrer mais il en vaut la peine.

OneSignal vous permet d’envoyer quasiment toutes vos notifications et de surtout mesurer leurs impacts respectifs. OneSignal intègre parfaitement bien cette notion de reporting.

Cependant les fonctionnalités qui m’auront le plus servi n’auront pas étaient celle-ci.

Segments

OneSignal vous offre la possibilité de générer vos segments d’utilisateurs en fonction de :

  • Nombre de sessions
  • Durée des sessions
  • Première sessions
  • Latitude & Longitude
  • etc.

Grâce à ça vous allez pouvoir envoyer des notifications propres à chaque segments. Manuellement ou automatiquement.

Template & A/B Testing

Là ça devient très puissant. OneSignal va vous permettre d’envoyer automatiquement une notification bien précise lorsqu’un utilisateur rentre dans un segment défini.

Par exemple : nous avons défini dans MyBetFriend un segment « Hardcore users » pour les users dépassant plus de XX sessions. C’est donc à ce moment là que nous lui demandions de nous noter sur le store.

Une fois cette technique mise en place nos reviews 5 étoiles furent régulières.

Et pour bien optimiser ce processus, OneSignal vous propose de réaliser des A/B Tests pour définir le message le plus pertinent.

Que du bonheur !

Branch.io

Dernier SDK pour la route : branch.io

Bon là on frise l’indécence, l’obscène même. Toujours gratuit, ce SDK va vous permettre de générer notamment des deeplinks.

Ces liens (magiques) vont intelligemment comprendre sur quel appareil le lien est ouvert et appliquer un scénario différent.

Exemple : Si vous êtes sur un BlackBerry vous pouvez paramétrer l’ouverture du store BlackBerry bien la redirection vers votre landing page, ou bien votre liste Mailchimp.

Le SDK n’est pas évident à mettre en place, mais les deeplinks sont très puissants pour faciliter le partage. Un bémol toutefois, si vous utilisez un raccourcisseur d’url comme nous, il se peut qu’il soit mal interprété. C’est en ce sens que je vous invite à implémenter un SSL sur votre site et utiliser donc un shorter idoine.

Branch.io propose également un onboarding personnalisé. Même si cette feature nous a un temps intéressé nous l’avons (malheureusement) délaissé au profit d’autres fonctionnalités.

Néanmoins il va sans dire que pour notre V2 nous allons utiliser à fond cette feature.

Toutefois, la feature qui aura été des plus puissantes dans notre cas d’utilisation c’est la feature app banner. Même chose, selon votre device, cette banner s’ajoutera en haut de votre site réagira de différents manières :

  • Ordinateur : La possibilité d’inscrire son numéro de téléphone pour recevoir un deeplink d’installation
  • N’importe quel mobile : L’installation en renvoyant sur le ou les bons stores
  • Un mobile où l’application est déjà installée : L’ouverture de l’application
  • Et un autre mobile où l’application est déjà installée mais non à jour : La mise à jour de l’application

C’est grâce à cette banner que nous avons pu réaliser l’un de nos « hacks » les plus efficaces.

La publicité pour installation d’application étant hors de prix (1€ en moyenne) le fait d’envoyer du trafic uniquement sur notre site (CPC faible sur le foot) eut pour effet d’optimiser notre investissement.

Soit l’internaute téléchargeait l’application, soit il laissait son mail ou soit et bien il générait du trafic sur notre site. Pour ainsi dire nous évitions toutes pertes d’investissements. Si vous êtes en plus l’heureux détenteur d’un blog et/ou d’un site drainant pas mal de visites quotidiennes vous allez pouvoir assister à un bond spectaculaire (je l’espère) de vos installations.

SDK Bonus, Launchkit.io

Dernier SDK et pas des moindres, Launchkit. Récemment acheté par Google, ce SDK nous a permis de gagner énormément de temps sur :

  • Génération des images iOS (apparemment plus besoin maintenant…)
  • Onboarding
  • Review monitor

Ils ont récemment déployé sur git l’ensemble de leurs codes. A voir ce qu’ils vont réaliser par la suite avec Google.

En espérant que cet article t’a plu, on peut se retrouver sur les Internets ici. On discutera de pannes serveurs et d’AdminSys, tu verras c’est rigolo :

Enrichir sa liste de prospects grace à Excel

Hello !

Le mois dernier la team deux.io m’a contacté pour réaliser un article orienté Growth Hacking. Ravi de la proposition j’ai rédigé un article traitant de la possibilité d’enrichir ses bases mails via Full Contact & Seo Tools for Excel.

Pour lire l’article c’est par ici :

hack-enrichir-liste-prospects-750x374

Grâce à cette technique vous allez pouvoir trouver des informations très intéressantes uniquement grâce à un email.

Par exemple, vous pourrez trouver le compte twitter, instagram, linkedin, facebook, quora, github etc… associé à cette adresse mail.

Ainsi si vous êtes dans une étape early stage avec des landing pages qui alimentent des listes Mailchimp, vous allez pouvoir créer votre communauté et surtout pouvoir commencer à échanger avec vos utilisateurs.

Newsletter & Slack ? C’est par ici !

Comment utiliser IFTTT et analyser les actions mises en place ?

Un article pour prendre en main IFTTT et analyser son impact

IFTTT comment ça marche ?

Vous avez déjà entendu parler d’IFTTT et vous vous demandez qu’est ce que c’est, à quoi ça sert et comment je vais pouvoir mettre en place cet outil ?

Pour comprendre IFTTT il suffit juste de comprendre son acronyme. IFTTT signifie IF This Then That. En clair une action est déclenchée (nous parlons ici de Trigger) et cette dernière génère une autre action préalablement définie.

Exemple très simple, je paramètre que si un Tweet avec le hashtag #doritos est émis alors IFTTT postera un status Facebook avec #doritos et d’autres mentions souhaitées.

Pour le générer rien de plus simple, il suffit d’aller sur IFTTT, se créer un compte, activer ses channels Twitter et Facebook et c’est parti.

C41UG3Jz7a

 

Ce qui est particulièrement bien réalisé chez IFTTT c’est cette facilité de mise en place et le nombre de channels proposés.

iftttchannels

 

Pour s’y retrouver par la suite ça peut vite devenir compliqué c’est pour cela que je vous propose la méthodologie suivante

Comment se servir d’IFTTT ?

Au risque de vous décevoir, je n’ai pas de recettes miracles pour l’utilisation d’IFTTT. Surtout au vu du nombre de channels proposés.

En effet, votre cible et votre produit vous est spécifique. Impossible donc de vous dire quelle recipes magiques vous devez utiliser pour générer LA combinaison parfaite.

Mais je vais quand même vous aider un petit peu en vous donnant une matrice Excel (téléchargeable plus bas) pensée par Olivier Sénant CMO de Droniris.

ifttttableau

En ordonnées vous trouverez vos différents triggers et en abscisses les actions déclenchées.

Exemple: Je veux que sur un hastag prédéfini sur le channel 1 IFTTT publie un post sur le channel 4. Il me suffit de l’inscrire sur l’intersection pour m’y retrouver et réfléchir au prochain recipe.

Grâce à cette matrice vous allez ainsi pouvoir plus facilement réfléchir à une stratégie IFTTT qui vous conviendra.

Ce qui peut être intéressant à réaliser, c’est l’imbrication des différentes recettes que vous avez conçus. Cela revient à redéfinir un trigger qui est une action générée par IFTTT.

Par exemple:

Trigger: Tweet #doritos

Action: Statut Facebook + #cheese

Trigger: Statut Facebook contenant #chesse

Action: Instagram post + #chips

Ça parait super comme ça mais ça ne l’est pas du tout ! En réalité vous allez générer du post pour du post sans pouvoir mesurer leurs impacts.

Ce qui nous intéresse en réalité c’est d’identifier les recipes qui marchent le mieux et surtout de comprendre pourquoi.

Les datas ne valent pas grand chose si vous n’êtes pas en mesure de les faire parler.

Méthodologie d’analyse

Pour pouvoir constituer une base de données propre, il faut que chaque recipe soit associé à un identifiant unique.

Cet identifiant vous permettra de visualiser rapidement sur votre outil de tracking l’impact généré par un recipe bien précis.

Par exemple, votre premier scénario IFTTT donne:

Pour un Tweet posté je relaie ce dernier sur mon mur Facebook

1er caractère : T pour Trigger

2nd caractère : T La première lettre du channel, ici Twitter

3ème caractère : A pour action

4ème caractère : F Le channel qui agit, ici Facebook

5ème caractère : 1 Le numéro du scénario d’automatisation

Ce qui donne comme identifiant unique: TTAF1

Vous n’avez plus qu’à associer cet identifiant unique à votre lien et récupérer les données qui vous intéressent.

Mais si vous avez un grand nombre de recipes à tracker ça risque d’être un peu fastidieux. C’est pour ça que je vous ai crée ce petit template Excel qui génère vos URL à tracker en fonction de vos différents scénarii.

excel-database-most-used Tracker ses recipes #IFTTT dans #Excel Click To Tweet

En espérant que cet article vous aura été utile ;)

L’inscription pour la newsletter ainsi que le Slack c’est par ici: