Comment démarrer un nouveau site eCommerce en 2015

J'ai été amené récemment à expliquer tout ce qu'il faut mettre en oeuvre pour démarrer un site de eCommerce en 2015  pour qu'il soit rentable.

Je pensais qu'il s'agissait d'un exercice évident et qu'une heure serait suffisante pour faire le tour de tout ce qu'il faut prendre en compte dans l’équation, en réalité au bout de 2 heures je n'avais toujours pas terminé tellement il fallait répondre aux questions que se pose un néophyte, aussi je profite de ce blog pour rendre tout ça plus clair.

Avant de commencer voici 2 choses qu'il faut vraiment avoir en tête :

99% des visiteurs de votre site n’achèterons rien au début.

D'après une étude de la Fevad 4140 sites en France font plus de 1 million d'euro de CA par an sur 138 000 soit 3% en 2014.

Je précise que j'ai développé une plateforme eCommerce et un ERP et je m'occupe de plusieurs sites eCommerce depuis 2010 dont 2 font plus de 1M€/an avec un largement.

Beaucoup de choses ont bien changé depuis 5 ans, notamment le nombre de sites (obligatoirement concurrent) en forte hausse,  Dans les années 2000 tout était facile, il n'y avait qu'à se baisser pour ramasser la mise. Maintenant la concurrence est beaucoup plus rude et placer des pages dans les résultats de recherche est devenu très difficile. Bref le ticket d'entrée est largement plus cher.

Alors pour lancer un site rentable en 2015 il va falloir être très très bon sur 4 points,
Le front web, il s'agit de ce que voient vos clients.
Le back il s'agit de la partie gestion de stock, commande fournisseur, relation client, la logistique.
Le trafic, la façon dont vont venir vos nouveaux clients, on retrouve sur ce poste la partie SEO/SEM,
Le tracking, dans ce poste il s'agit de mesurer et d'analyser des tonnes et des tonnes de données pour déterminer le retour sur investissement de vos différentes actions.

La valeur en pourcentage à coté des 4 postes est l'impact global de celui-ci que j'estime sur l'ensemble de l’équation.

1 - Le front (10%)


Lorsque l'on démarre une activité eCommerce, le première chose qui vient à l'esprit est l'aspect du site web, c'est bien légitime, mais ce n'est qu'une petite partie de l’équation globale. Dans un premier temps, ce que je conseille c'est surtout de respecter les grandes lignes ergonomiques. Le livre d'Amélie Boucher "Ergonomie Web Illustrée" est à lire pour avoir une vision des règles ergonomique, en fonction des produits que l'on vend.

Le design du site n'a pas la même importance, si vous vendez des vêtements ou chaussure de mode, il faudra faire un site vraiment sexy, ou si vous vendez des produits techniques, elle sera moindre.

A savoir il y a énormément de thèmes sur le site http://themeforest.net/ qui peuvent largement convenir.

Dans le cas d'un nouveau site, il faut bien entendu que le site soit "responsive" et puisse s'adapter aux différents devices (desktop, tablette, smartphone).

L'ergonomie

Le client ne doit pas s'inscrire obligatoirement pour passer une commande, privilégiez les commandes "anonymes" sans inscription.
Le client doit pouvoir se connecter à l'aide de ses identifiant de réseau social (facebook, twitter, google+, microsoft).
Le client doit pouvoir filtrer les résultats de recherche via une navigation à facette, (prix, categorie, couleur, en stock, livraison gratuite, rating).
Le moteur de recherche doit être utra-pertinant, n'oubliez pas que pour madame Michu, la normalité c'est Google, elle ne comprend pas si l'affichage des résultats ne correspond pas à ce qu'elle demande.
La fiche produit doit être la plus exhaustive, les photos doivent être de très bonne qualité, une vidéo est un plus (si possible). Le bouton d'ajout au panier doit être clairement accessible.
Afficher le niveau de stock est maintenant obligatoire ainsi que les délai de livraison rendu chez le client.
Les client doivent pouvoir noter les produits.

La technologie

Plusieurs solutions s'offrent à vous. soit vous ne voulez ou ne pouvez pas avoir de prestataire technique , dans ce cas il faudra opter pour le cloud, sinon la version hébergée mutualisée ou dédiée, et si vous avez déjà des developpeurs en interne optez plutôt pour une version custom.
Gardez en tête que votre site doit être très rapide et répondre en moins d'une seconde pour chaque page. Au delà vos ferez fuir vos clients et vous serez moins bien indexé par les moteurs de recherche.

Version cloud

L'idée est de vous proposer une solution clé en main, qui comprend l’hébergement total de votre site sur un serveur, vous n'avez plus qu'a choisir un thème, le personnaliser et faire les réglages nécessaires au fonctionnement du site pour démarrer.

Le paiement s'effectue en fonction du nombre de visiteurs, ou en fonction du chiffre d'affaire selon les plateformes.

Version hébergée


L'idée est de télécharger les composants nécessaires en fonction de la technologie que vous avez choisi et d'installer ceci sur un serveur web partagé ou dédié.

Version custom

Si vous avez les ressources en interne qui vous permettent de reprendre des plateformes existantes (magento, prestashop, ou autres) ou partir complètement de zéro pour les guerriers ;)


A savoir je vais y revenir plus tard dans un chapitre sur le trafic, il faut prendre la bonne décision au départ sur le plan technique en fonction de vos projections de croissance, si elle est très forte et rapide et que vous avez opté pour une version cloud dont le paiement s'effectue en fonction du chiffre d'affaire, ça peut devenir très cher par rapport au service rendu. D'autre part changer de technologie peut coûter assez cher.

Les fonctionnalités

- Vous devez pouvoir proposer la livraison directement chez le client, proposer éventuellement des créneaux horaires, mais aussi en point relais. Si possible afficher une livraison gratuite à partir d'un certain montant.
Un conseil, affichez dès le panier de commande les différentes possibilités de transport et les tarifs clair qui sont pratiqués ceci améliorera le taux de passage à l’étape de saisie des coordonnées de livraison.
- Vous devez proposez le plus possible de moyen de paiement, CB, Paypal, avec ou sans 3D Secure en fonction des montants et du risque que vous estimez prendre. Si les montants sont élevés, pensez à proposer le paiement en plusieurs fois et le débit à la livraison.
- Le panier doit être stocké le plus longtemps possible sur votre serveur tant que le client ne l'a pas encore converti en commande, n'utilisez pas de plateforme qui propose de ne garder le panier que le temps de session utilisateur.
- Le client doit pouvoir vous joindre au téléphone qui doit être affiché clairement sur le site sur chaque page, n'utilisez surtout pas de numéro surtaxé mais plutôt un numéro azure ou vert.
- Il existe des systèmes de chat en ligne moins intrusif que le téléphone mais il faut toujours être derrière sinon ça ne fonctionne pas.


2 - Le back (30%)


A la rigueur avoir un bon front eCommerce qui vous permet de prendre des commandes, c'est relativement facile, c'est après que ça devient compliqué. Il va vous falloir une très bonne gestion de stock, c'est une des clés de la réussite, vous devez pouvoir coupler les valeurs de stock de vos produits sur le front web en temps réel.

La relation client

Sur le site le client doit pouvoir visualiser l'ensemble des commandes qu'il a passé sur le site et sur celle en cours savoir ou en est la préparation ou le transport avec le maximum de détail.
S'il téléphone, vous devez également pouvoir le renseigner de la même manière, pouvoir lui envoyer des emails (confirmation de commande, changement de mot de passe, autologin).
Si vous avez vendu des produits qui sont en rupture de stock et que votre fournisseur est en retard vous devez être notifié de ce retard et pouvoir envoyer un email au client lui signifiant ce retard avant qu'il vous appelle (très important).

Le stock

Votre système d'information doit vous indiquer clairement les niveaux de stock, vous proposer des stock mini en fonction du volume de vente, avoir une classification ABC automatisée, avoir la possibilité de gérer plusieurs entrepôts, gérer les date d'expiration pour les produits périssables et les numéro de lot et/ou de série pour les produit onéreux et sous garantie, permettre la livraison directe depuis le fournisseur.

La relation fournisseur (achats)

Vous devez pouvoir passer vos commande de manière automatisée chez vos différents fournisseur, avoir l'historique des prix pratiqués.
Vous devez avoir un système qui vous prévient dès qu'un fournisseur n'a pas livré à la date qu'il vous à indiqué antérieurement et pouvoir le relancer facilement.
Vous devez pouvoir acheter si possible un même produit chez plusieurs fournisseurs pour faire jouer la concurrence.
N'oubliez pas qu'un visiteur sur votre site sera probablement passé par différents comparateurs de prix , vous ne pourrez pas trop jouer sur le prix de vente, par contre il va falloir vraiment travailler le prix d'achat pour augmenter votre marge, pour cela il faut exploiter un maximum d'informations (historique des prix, gratuité, échantillon, retards, concurrence avec d'autres fournisseur, délai d’approvisionnement).

La logistique

La logistique est cruciale, c'est la que vous fidélisez vos clients, avec des acteurs comme Amazon qui livre à la perfection en temps et heure, c'est devenu la normalité, vos clients ne tolérerons aucun retard et vous le ferons savoir soit par téléphone ou sur les réseau sociaux et vous perdrez beaucoup de temps à leur expliquer vos retards.
Jusqu'à 10 commandes par jour, il est facile de préparer les commandes en temps et heure, c'est au delà de ce volume que les choses se compliquent, en effet, vous allez avoir probablement 2 clients qui vous commanderons le même produit au même moment alors que vous n'en avez qu'un en stock, de la même manière votre client peut vous commander plusieurs produits et un des produits est en rupture, il va la encore vous falloir faire des choix.
Négociez tout le temps avec les transporteurs en fonction du volume.
Sans un bon algorithme vous n'aurez aucune chance de monter en volume.

La facturation

En BTOC vous devez pouvoir envoyer des factures clair et légales au format PDF , le client doit avoir la possibilité de les récupérer a posteriori sans vous en faire la demande.
En BTOB c'est vraiment un plus de gérer un compte client avec la possibilité de coupler celui-ci avec un système d’affacturage de manière à permettre de gérer un encours et favoriser la fidélité.

Comptabilité

Votre système doit permettre l'export des factures vers votre comptabilité c'est évident mais aussi pouvoir faire les lettrages par rapport aux différents systèmes de paiement mis en place et rapprocher les CBs avec les factures de manière automatisée, attention si votre site prend beaucoup de commande ce poste est très chronophage, ne pas le négliger.

3 - Le trafic (40%)

Une fois que le site web est en place, il va falloir se faire connaitre, j'ai réalisé une map qui recense 10 sources de visites principales.


Certaines sont payantes d'autre gratuites, dans le cas qui nous intéresse (nouveau site), la partie gratuite ne sera pas d'une grande aide au départ.

Les réseaux sociaux

Soyez présent, créez les différents comptes pour pas vous les faire prendre (facebook, twitter, pinterest). 

Si votre marque n'est vraiment pas connue, ne vous fatiguez pas avec les réseaux sociaux, ils ne vous rapporterons strictement rien.

Les comparateurs de prix

Il existe des dizaines de comparateurs de prix, certains gratuits d'autres payants, les modes de rémunération sont généralement au Coût Par Click (CPC), la moyenne constatée est de 0.2€ par clic.

Chaque comparateur à son format de fichier pour fonctionner, il s'agit d'exporter une sélection de produits au bon format pour figurer dans leurs pages.

Autant dire qu'avec un CPC à 0.2 en moyenne cela handicape les produits à petit prix (moins de 5 euros) car si votre marge sur ces produits est de 30% elle sera vraiment impactée via ce mode de vente. Nous verrons dans le chapitre modèle économique comment faire le calcul.

J'attire votre attention sur le fait que vous risquez d’être surpris si vous utilisez Google Analytics ou tout autre système pour mesurer les visites du site, en effete le nombre de clics entre le nombre relevé par celui-ci et ce que facture le comparateur, généralement on retrouve 20% de clic en plus en faveur du comparateur bien sur. Ceci vient du fait que le mode de comptage est spécifique au comparateur, par défaut 1 clic par page par IP quelque soit la durée dans le temps.

Tous les comparateurs vous diront qu'ils gèrent le "click-fraud", mais la confiance n'exclue pas la vérification, certain sont à surveiller plus que d'autres , notamment ceux qui commencent par K ou T ;)

Vous pouvez utiliser des systèmes comme Lengow ou ShoppingFlux pour générer les différents formats de fichier dont ont besoin les comparateurs, l'avantage est que vous générez un seul flux au départ et eux s'occupent de convertir celui-ci pour le rendre compatible avec eux. Attention ce service à un coût non négligeable en fonction du nombre de produits, et il y a un gros travail de classification de vos produit à produire quand même.

Google Shopping 
C'est devenu le plus gros comparateur maintenant, il est incontournable, ce qui le caractérise, c'est qu'il s'agit d'un système d’enchère configurable dans AdWords, il est possible de jouer sur différents facteurs par défaut comme (la marque, la catégorie, le code produit) mais aussi des paramètres personnalisés comme par exemple (le stock, la marge, le nombre de concurrent, ect...) vous avez le droit à 5 et ceci avec une hiérarchie très bien faite. Il n'y a pas de problème de comptage de clic avec ce système. Comptez plutôt 0.25€ avec lui voir beaucoup plus sur certaines catégories de produit, c'est clairement le plus cher mais aussi le plus efficace en terme de trafic quand il est bien configuré. Il est possible de récupérer la liste des mots clés avec lesquels ont été cliqués les annonces, malheureusement le niveau de visibilité s’arrête à la campagne, il n'est pas possible de corréler (pour l'instant j'espère) avec la fiche produit. A savoir l'ordre d'affichage des résultats de recherche est fonction de votre enchère et non pas de votre prix , ce qui veut dire qu'un concurrent plus cher que vous peut apparaître avant vous.

Leguide 
C'est un très bon comparateur (honnête), le CPC est fixe quel que soit le produit, il est possible d'utiliser un système de mise en avant un peu plus cher ou de bénéficier de leur newsletter. A titre perso j'ai utilisé les 2 derniers sans résultat probant. Leur back-office est famélique même s'il à été rafraîchi récemment, ne comptez pas sur eux pour avoir des statistiques poussées sur les clics, il ne fournissent pas les mots clés avec lesquels vos visiteurs sont arrivés sur vos pages mais on peut les récupérer dans le referer , ce qui est un très bon point. Attention il n'est pas possible de réaliser des campagne avec un montant fixe par jour, c'est tout ou rien avec eux donc le budget peut être important et incontrôlable. Ce comparateur possède un système de notation interne basé sur des points comme l'ergonomie de votre site, le prix de vos produits, les services. Si vous avez une bonne note globale vous apparaîtrez en premier même si votre prix est supérieurs a vos concurrents (ce qui peut être contre-productif, en cas d’écart important de prix). La facture est succincte juste le nombre clics sans détail.

Kelkoo
J'ai une expérience pas très réussie avec ce comparateur, il génère énormément de trafic non qualifié (pas des acheteurs), masque totalement les referrers ce qui fait que l'on ne sait pas sur quel mot clé ni quelle page du site viennent les visiteurs. La facture est succincte sans détail, bref il faut une certaine confiance pour travailler avec eux. Le CPC est fixe

Twenga
Comparateur classique générant de moins en moins de trafic probablement a cause des differentes optimisations de google, je les retrouve de moins en moins dans les SERP. 
Le cpc est fixe
Pas de referer possible et facture succincte n'indiquant que le nombre de clic, donc attention.

Tous les prix
Très bon comparateur très honnête, c'est le seul avec lequel je trouve le même nombre de clics dans google analytics et leur facture, malheureusement génère peu de traffic, pas de referer

Shopzilla
Ils utilisent un système d'enchère incompréhensible avec un classification des produits pas très pratique, je n'ai pas eu une experience réussie avec eux. Par contre vous avez le détail de vos clics.

Idéalo
Véritable comparateur de prix exhaustif avec un ordre d'affichage par tarif produit comprenant les frais de port, génère peu de trafic, peut être un bon complément pour certains produits dont on sait qu'on est bien placé niveau prix. Possibilité de récupération du referer pour connaitre les pages ou se trouvent ses produits (bon point). Facture non détaillée. Trop cher pour le service rendu néanmoins.

Hellopro
Si vous êtes plutôt en BTOC, ce comparateur peut être intéressant, j'ai une expérience en cours avec eux en ce moment pas très probante, juste l’équilibre au niveau ROI. Ils masques les referers, la facture est succincte.

Blog ou forum

Maintenir un blog à coté d'un site de eCommerce est une bonne idée s'il ne tombe pas à l'abandon au bout de quelque temps faute de temps ou d'inspiration pour l'alimenter, un conseil tout de même mettez plutôt le paquet sur vos fiches produits, rédigez les comme le billet d'un blog.
Certains site eCommerce mettent à disposition un forum d’entraide ça peut être une bonne idée si vous vendez des produits techniques qui demande beaucoup d'informations auxiliaires concernant leur utilisation (informatique, hi-fi, bricolage, ect). 

Au global il s'agit d'une source qui peut vous amener énormément de visites, j'ai en tête l'exemple d'un site avec qui je travaille dont l'essentiel du trafic provient de ses pages magazine que l'on peut assimiler à un blog  http://www.plantes-et-jardins.com (groupe Gamm Vert)

Régies publicitaires

Au début de la vie de votre site eCommerce c'est essentiellement de cette source que viendra votre trafic.

Il existe 3 types de plateforme avec chacune leur spécificités

a - Les liens sponsorisés

Le maître absolu est bien sur Google Adwords, vous définissez des listes mots clés puis vous créez des campagnes qui comprennent des groupes d'annonces. Il est possible de budgéter chaque campagne pour une dépense quotidienne. Attention si vous êtes novice dans ce domaine faite vous obligatoirement accompagner au moins au début pour comprendre le fonctionnement. Attention sur certain mots clés, ça va très très vite pour dépenser beaucoup.
Un nouveau venu est Facebook ou il est également possible d'acheter des annonces sponsorisées avec plusieurs formats possibles , le coût est bien moindre qu'AdWords et le ciblage bien entendu beaucoup plus précis, mais malheureusement les personnes qui sont sur Facebook ne sont pas la pour acheter donc la perf est pitoyable (en tout cas ce que j'ai pu tester).
Twitter fait son entrée depuis quelques mois en France, je n'ai pas encore testé.

b - Les bannières

Si vous avez la possibilité de créer des bannières, ce mode de publicité peut être intéressant par exemple à placer sur des sites à fort trafic comme Leboncoin ou d'autres, attention c'est très très cher.

c - Le retargeting

Dès qu'un visiteur arrive sur votre site, vous pouvez placer un cookie qui permettra par exemple à une plateforme comme Critéo (largement la plus efficace) d'afficher des publicités ciblées sur les autres sites que visitera votre client par la suite s'il n'a pas réalisé une conversion en commande. La rémunération se fait au CPC , comptez un  peu moins de 0.2€ par clic, une plateforme comme Critéo demande un certain trafic avant d'ouvrir le robinet, il est possible d'utiliser AdWords pour faire du retargeting, mais c'est largement moins efficace et très fastidieux à configurer.

Marketplaces

Il est possible de "bénéficier" du trafic des mastodonte du web tel que Amazon, CDiscount, PriceMinister, LaRedoute et autres, ces places de marchés s'occupe de placer vos produits sur leurs sites, s'occupe de la partie marketing en amont, lien sponso, référencement naturel (attention ceci n'est pas une bonne nouvelle pour vous) et réalise la transaction. Vous "n'avez plus" qu'a livrer la marchandise. En contrepartie les marketplaces vous préleverons en moyenne 17% du montant de la vente, ça peut aller plus haut en fonction des produits. A ceci il faut que vous ajoutiez le transport et le SAV (produits à faible marge passez votre chemin).

A la rigueur utilisez ces places de marché que si vous ne voulez pas gérer de site eCommerce et que vous avez un excellent sourcing avec des produits dont la marge peut dépasser 40%, dans le cas contraire ceux-ci vous cannibaliseront votre référencement naturel, vos clients et surtout votre cash.

Si une commande se passe mal, ils sont capable de bloquer votre compte surtout les marketplaces dont le nom commence par A

Un conseil, évitez les !

Newsletters

Cette source est un très bon canal pour faire venir du monde sur votre site, mais attention ayez du concret à proposer, le taux d'ouverture des email est de l'ordre de 20% et environ 8% de clic. Vous pouvez utiliser un prestataire pour faire partir vos emails, l'avantage étant qu'ils savent gérer la dérivabilité, le tracking d'ouverture et de clic et le bouncing (échec d'envoi, email erroné, IP blacklistée), mais ceci à un coût non négligeable à négocier avec chaque plateforme. Ayez aussi à l'esprit que vous leur fournissez tous les emails de vos clients, donc choisissez bien votre prestataire.


Affiliation

L'avantage de cette source de trafic est qu'elle est gratuite et peut vous faire gagner beaucoup en visibilité rapidement, le prix a payer est une commission entre 3% et 10% du montant de la transaction, le paiement étant à la performance. Attention toutefois à bien surveiller les affiliés, ils ont une fâcheuse tendance à sur-optimiser le placement des cookies pour s'attribuer le maximum de ventes. Un conseil , au départ faites vous accompagner par une agence qui sait maîtriser cette problématique, les principaux acteurs sont : (NetAffiliation,Efiliation,WebGains,Clickvalue).

Le référencement naturel

C'est la source de visite qui vous rapportera logiquement le plus d'argent car elle ne coûte en théorie rien du tout. En France Google cannibalise 95% des recherches, aussi ne vous fatiguez pas avec les autres , ils suivront vos optimisations pour google.

Pour votre nouveau site, votre fiche produit doit être parfaite il faut penser comme google et se donner des pénalité en fonction de ce qui ne va pas.

Titre de la page trop long +70 caractères (par exemple)
Trop de majuscules dans le titre de la page
Ect...

Votre système d’édition de fiche produit doit pouvoir vous indiquer les différentes règles et vous alerter dès qu'une règle n'est pas respectée.

Au début vous ne connaîtrez pas vos mots clés, vous pouvez les déduire de vos fiches produits mais la réalité sera probablement tout autre. 

Depuis 2 ans google masque les mots clés quand un visiteur vient du moteur de recherche dans 90% des cas, autant vous dire que vous n'aurez que des miettes, les solutions  pour savoir avec quels mots clés vous êtes référencés ne sont pas nombreuses. 

Vous pouvez utiliser ce que vous donne Google Webmaster Tools c'est bien fait et assez exhaustif, mais vous ne connaîtrez pas vos concurrents. 
Vous pouvez utiliser des services comme SEM Rush , c'est payant et c'est très bien fait, vous pouvez voir votre concurrence et suivre la perf de vos mots clés.
Si vous ne voulez pas payer, si vous êtes assez technique, vous pouvez crawler vous même vos positions, mais attention sur les gros volumes (plusieurs milliers de mots clés) , google ne veut pas qu'on le crawl et dispose d'un anti-crawl très préformant qui blackliste votre IP pendant un long moment en cas de détection.

Pour un nouveau site, il va falloir être patient , très patient avant de voir apparaître vos pages dans les résultats de recherche, comptez au moins 6 mois, sauf si vous avez vraiment du contenu original.

Avec les différents algorithmes mis en place via Panda (Contenu) et Pingouin (Backlink) il devient de plus en plus difficile d'intervenir "artificiellement" sur les résultats de recherche pour gagner des positions, je vous conseille de miser votre budget sur vos fiches produits, travaillez le contenu à la perfection, utilisez les balises sémantiques , faites notez vos produits par vos clients, c'est le moyen le plus sur pour gagner des positions.

L’intérêt d'utiliser un référenceur est de plus en plus limité pour des résultats incertains qui peuvent ne plus fonctionner avec la mise en place d'un nouvel algo chez google.

Offline

Campagne radio, flyer dans les boites aux lettre, pub magazine, voire pub tv pour les plus riches, c'est une possibilité mais sachez que vous aurez le plus grand mal pour calculer votre retour sur investissement via ces canaux il faut vraiment être riche pour utiliser ces medias.

4 - Le tracking (20%)

Ne faite rien si vous ne pouvez pas mesurer votre retour sur investissement !

C'est une composante très importante dans le eCommerce et une réelle chance par rapport aux médias traditionnels telle que la presse, la télévision ou la radio. Vous pouvez très précisément savoir d'ou viennent vos visiteurs, et ceci grâce à de petits bouts de code que vous devez placer aux bons endroits dans toutes vos pages web.

L'outil gratuit incontournable qui vous fournira le plus d'information sur vos visiteurs est Google Analytics (toujours google...). Mais attention avec les conversions , son algorithme est basé sur de l'échantillonnage, dès que l'on monte en volume et la précision s'en ressent. 

Chaque campagne marketing doit être marquée via des paramètres spécifiques dans les liens entrants de manière très précise, que ce soit avec des comparateurs de prix, des liens sponsorisés, des newsletters ou autres réseaux sociaux.

Grace à ces marqueurs vous saurez précisément quelle sont les médias qui performent.

Ce n'est pas suffisant de savoir  d'ou viennent les clics, il va falloir en fonction des sources de visite savoir s'il y a des conversions et la ça se complique. Pour cela il faudra placer des bouts de code dans les pages de conversion (confirmation de commande), mais certains moyens de paiement comme kwixo ne vous donne pas tout de suite l'accord de vente, il peut se passer une journée, et leur serveurs ne discute qu'avec votre serveur sans passer par votre client dans ce cas il devient difficile de remonter la conversion.

Une bonne solution logicielle doit pouvoir suivre toute la chaîne de conversion de bout en bout, désactiver automatiquement les produits qui ne performent pas, et pousser ceux qui réalisent le plus de chiffre d'affaire. Plus vous aurez de produits plus ces solutions seront indispensables.

Il faudra également surveiller jour par jour avec des courbes de tendance chacun de ces indicateurs appelés KPI

http://mind42.com/mindmap/8f73cd86-2030-4a78-9e42-26790489f7cc

Le modèle économique


Comme indiqué tout au long de ce billet il n'y a pas grand chose de gratuit dans le eCommerce surtout au début.

la base c'est de déterminer le panier moyen en fonction des produits que vous vendez, puis vous partez sur un taux de conversion de 1% et vous vos conversions par celui-ci ce qui vous donnera votre CA.

Par exemple si vous vendez des vêtements le panier moyen se situe aux alentours de 50 euros. Si vous arrivez à faire venir 1000 visiteurs par jour sur votre site, vous aurez alors 10 conversions soit un CA de 500 euros.

Dans le domaine des vêtements la marge moyenne est de 50% (Coeff 2.0) soit un bénéfice brut de 250€.

La dessus vous devez déduire votre trafic sponsorisé, comme indiqué plus haut le CPC moyen est de 0.25€ sur AdWords , pour faire 1000 visites il vous faudra dépenser 250€.

Oui, il reste zéro pour vivre.  Et encore il vous reste à payer les salaires, la location de l’entrepôt, les transactions bancaires, l’hébergement du site, et beaucoup d'autres choses. 

Maintenant que faut-t-il faire pour rendre rentable le site web ?

C'est la qu'intervient tout ce que j'ai cité plus haut, ce sont ces points qui vont vous permettre de rendre votre site rentable.

1 - Augmenter le panier moyen

Incitez vos clients à ajouter plus de produits dans leur panier grâce aux ventes croisée (cross-selling) l'idée est de proposer les produits qu'ont acheté statistiquement d'autres client avec celui placé dans le panier (ceci fonctionne assez bien). Utilisez également les coupons de réduction pour inciter à mettre plus de produits.

2 - Réduire vos coûts d’acquisition de trafic

Ne misez pas tout sur AdWords , c'est le plus cher, faites un mix avec les comparateurs de prix ils sont 8 centimes moins cher en moyenne et chaque centime compte. Utilisez aussi l'affiliation c'est gratuit. 

3 - Augmentez votre taux de conversion

Éliminez les produits qui vous font du trafic mais jamais de conversion (voir partie tracking)
Travaillez vos fiches produits pour qu'elles soient parfaites
Fidélisez vos clients

4 - Augmentez votre marge

Mesurez les prix de vos concurrents et placez vous le mieux possible, sachez qu'il existe des écarts de prix considérables entre 2 tarifs pour un même produit , il suffit souvent pour vous de garder la même place en resserrant l’écart, exemple un concurrent vend un produit 100€ et vous 90€, placez vous plutôt à 99€ vous pouvez gagner 9€
Travaillez vos achats en volume ou fréquence avec vos fournisseurs pour gagner de ce coté la.
Négociez systématiquement vos coûts de transport.


En partant du principe que ces points ont été amélioré, nous allons refaire le calcul quelques semaines plus tard.

Le panier moyen est passé à 65 euros, ne nombre de visites est passé à 1500 / jour dont 1000 toujours payantes mais avec 50% d'AdWords et 50% de comparateur. et le taux de conversion est passé à 1.5% en moyenne. La marge est passée à 55% (Coeff 2.2).


1500 visites = 22 commandes à 65€ soit un CA de 65 * 22 = 1430€ 
Cout du trafic de 500 * 0.25 (AdWords) + 500 * 0.17 (Comparateurs) = 125 + 106.25 = 231.25€
5 ventes ont été réalisées via un système d'affiliation avec un taux de reversement de 6% 
5 * 65 * 0.06 = 19.5€
La marge est de 55% soit un bénéfice brut de 786€

Si l'on retire le coût du trafic et l'affiliation 786 - 231 - 19.5 = 555€

A vous de voir maintenant si ce montant dépasse votre seuil de rentabilité, si c'est le cas, vous allez progresser !





Comment utiliser Unity avec Asp.Net WebApi MVC4 RTM

La version RTM d’asp.net MVC4 est maintenant disponible à l’adresse suivante : http://www.microsoft.com/en-us/download/details.aspx?id=30683

Il y a eu quelques changements entre la version Beta puis RC pour utiliser Unity avec WebApi, voici une solution, dans un premier temps il faudra utiliser la nouvelle version de unity disponible via NuGet :

image

Il faut ensuite instancier le container dans Global.asax de la manière suivante :

	public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);

var container = new Microsoft.Practices.Unity.UnityContainer();
container.RegisterType<Services.ValueService>();

System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new UnityServiceDependencyResolver(container);
}
}

Le dependency resolver de webapi est configurable, c’est ce que l’on peut voir à la dernière ligne , voici la classe utilisée :

	public class UnityServiceDependencyResolver : System.Web.Http.Dependencies.IDependencyResolver
{
Microsoft.Practices.Unity.IUnityContainer m_Container;
System.Web.Http.Dependencies.IDependencyResolver m_DefaultResolver;

public UnityServiceDependencyResolver(Microsoft.Practices.Unity.IUnityContainer container)
{
m_Container = container;
m_DefaultResolver = System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver;
}

public System.Web.Http.Dependencies.IDependencyScope BeginScope()
{
// This example does not support child scopes, so we simply return 'this'.
return this;
}

public object GetService(Type serviceType)
{
if (IsBuiltIn(serviceType))
{
return m_DefaultResolver.GetService(serviceType);
}
return m_Container.Resolve(serviceType);
}

public IEnumerable<object> GetServices(Type serviceType)
{
if (IsBuiltIn(serviceType))
{
return m_DefaultResolver.GetServices(serviceType);
}

return m_Container.ResolveAll(serviceType);
}

private bool IsBuiltIn(Type serviceType)
{
if (serviceType == typeof(System.Web.Http.Tracing.ITraceManager)
|| serviceType == typeof(System.Web.Http.Tracing.ITraceWriter)
|| serviceType == typeof(System.Web.Http.Dispatcher.IHttpControllerSelector)
|| serviceType == typeof(System.Web.Http.Dispatcher.IAssembliesResolver)
|| serviceType == typeof(System.Net.Http.Formatting.IContentNegotiator)
|| serviceType == typeof(System.Web.Http.Dispatcher.IHttpControllerTypeResolver)
|| serviceType == typeof(System.Web.Http.Dispatcher.IHttpControllerActivator)
|| serviceType == typeof(System.Web.Http.Controllers.IHttpActionSelector)
|| serviceType == typeof(System.Web.Http.Controllers.IHttpActionInvoker)
|| serviceType == typeof(System.Web.Http.Controllers.IActionValueBinder)
|| serviceType == typeof(System.Web.Http.Validation.IBodyModelValidator)
|| serviceType == typeof(System.Web.Http.Metadata.ModelMetadataProvider)
|| serviceType == typeof(System.Web.Http.Hosting.IHostBufferPolicySelector)
|| serviceType.FullName.Equals("System.Web.Http.Validation.IModelValidatorCache")
)
{
return true;
}
return false;
}

public void Dispose()
{
m_Container.Dispose();
}
}

L’idée c’est d’utiliser le resolver standard pour les types prédéfinis, a noter certains type comme IModelValidatorCache sont internal, pour tous les autres cas on utilise le resolver Unity passé en paramètre du constructeur, pour utiliser ses propres services et les resoudre par injection de dépendance.


Ci-dessous le controller sample “ValueController” refactoré pour utiliser un service prédéclaré :

	public class ValuesController : ApiController
{
public ValuesController(Services.ValueService valueService)
{
this.ValueService = valueService;
}

protected Services.ValueService ValueService { get; private set; }

// GET api/values
public IEnumerable<string> Get()
{
return ValueService.GetList();
}

// GET api/values/5
public string Get(int id)
{
return ValueService.GetList().ElementAt(id);
}

// POST api/values
public void Post([FromBody]string value)
{
ValueService.Add(value);
}

// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
}

// DELETE api/values/5
public void Delete(int id)
{
}
}

Le resultat est le suivant :


image

Comment compiler les vues d’un projet asp.net mvc

Il est possible de compiler toutes les vues d’un projet MVC, c’est plus simple pour retrouver toutes les erreurs de syntaxe possibles avant de les decouvrir en production Clignement d'œil

Pour cela il faut editer le fichier .csproj du projet asp.net mvc (a partir de 3) et retrouver l’élément suivant :

<MvcBuildViews>false</MvcBuildViews>
Remplacer la valeur par true
Ensuite tout en bas du projet il faut retrouver l’element suivant :
  <Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">     <AspNetCompiler VirtualPath="temp" PhysicalPath="$(WebProjectOutputDir)" />   </Target>
Remplacer par :

<Target Name="MvcBuildViews" AfterTargets="AfterBuild" Condition="'$(MvcBuildViews)'=='true'">
  <AspNetCompiler VirtualPath="/" PhysicalPath="$(WebProjectOutputDir)" TargetPath="$(WebProjectOutputDir)\..\temp" Force="true" Debug="true" LogStandardErrorAsError="false" />
</Target>


Ceci pour eviter l’erreur dans le ficher web.config “MachineToApplication” eventuel


et dernière chose ajouter l’element suivant ou completer sur le postbuild du projet :


<PropertyGroup>
  <PostBuildEvent>rd "$(ProjectDir)obj" /S /Q</PostBuildEvent>
</PropertyGroup>


Ce qui aura pour effet de supprimer tous les fichiers du repertoire obj qui pourrait compliquer la compilation des vues.


 

 

Comment mettre en place des tests unitaires avec asp.net mvc4

image

Ce post fait suite à une critique constructive dont j’ai fait l’objet via le projet opensource ERPStore concernant du code de test que j’avais écrit, la source se trouve ici :

http://hadihariri.com/2012/04/07/test-setups-and-design-smells/

Effectivement je reconnais que la version affichée sur cet exemple (V2) n’était pas bonne, pas sur le plan de l’héritage que je revendique et qui respecte le pattern DRY,  mais parce que l’injection de dépendance était écrite “en dur” dans une méthode d’initialisation qui pouvait ne pas correspondre à la réalité du site qu’elle était censée tester.

Quand on utilise de l’injection de dépendance avec asp.net mvc il est difficile de reproduire au plus proche le comportement du serveur, mais il est possible de reproduire le comportement d’une requête, pour cela j’utilise le framework Moq http://code.google.com/p/moq/ et NUnit http://www.nunit.org/  et “toujours” une classe de base abstraite TestBase

Cette classe possède une méthode initialize, il faudra appeler cette méthode dans toutes les classes de test qui hériteront de TestBase via l’attribut [SetUp] de NUnit.
 
  public virtual void Initialize()
{
var httpContext = GetHttpContext();

if (m_Application == null)
{
m_Application = new ERPStoreApplication();
m_Application.Initialize(httpContext);

}

var resolver = System.Web.Mvc.DependencyResolver.Current as IOC.UnityDependencyResolver;
m_Container = resolver.Container;

this.Logger = m_Container.Resolve<ERPStore.Logging.ILogger>();
}

 

Elle récupere ou crée un contexte Http via la Methode GetHttpContext()
  public HttpContextBase GetHttpContext()
{
if (m_MockHttpContext == null)
{
m_MockHttpContext = CreateMockHttpContext();
}
return m_MockHttpContext.Object;
}

Bien entendu nous n’avons pas lors des tests un serveur IIS avec une requete http en bonne et due forme, il va donc falloir en creer une de toute pièce , pour ce faire Microsoft a fourni les éléments nécessaires via l’assembly System.Web.Abstraction, il s’agit de wrappers (classes abstraites) utilisées par le serveur lors du traitement d’une requête, à savoir HttpContext (son wrapper HttpContextBase), Request et son wrapper RequestBase, Response, ect…, tout l’art est de pouvoir “bouchonner” ces wrappers pour récupérer un context http utilisable par les controllers. C’est la qu’intervient le framework Moq il va nous aider à creer des instances concrètes des differents wrappers.

  private Mock<HttpContextBase> CreateMockHttpContext()
{
var context = new Mock<HttpContextBase>();
var cookies = new HttpCookieCollection();

// Response
var response = new Mock<HttpResponseBase>();
var cachePolicy = new Mock<HttpCachePolicyBase>();
response.SetupProperty(r => r.StatusCode, 200);
response.Setup(r => r.Cache).Returns(cachePolicy.Object);
response.Setup(r => r.ApplyAppPathModifier(It.IsAny<string>())).Returns<string>(r => r);
response.Setup(r => r.Cookies).Returns(cookies);
context.Setup(ctx => ctx.Response).Returns(response.Object);

// Request
var request = new Mock<HttpRequestBase>();
var visitorId = Guid.NewGuid().ToString();
var principal = new ERPStore.Models.UserPrincipal(visitorId);
request.Setup(r => r.AnonymousID).Returns(principal.VisitorId);
request.Setup(r => r.Cookies).Returns(cookies);
request.Setup(r => r.Url).Returns(new Uri("http://www.test.com"));
request.Setup(r => r.Headers).Returns(new System.Collections.Specialized.NameValueCollection());
request.Setup(r => r.RequestContext).Returns(new System.Web.Routing.RequestContext(context.Object, new System.Web.Routing.RouteData()));
request.SetupGet(x => x.PhysicalApplicationPath).Returns("/");
request.Setup(r => r.UserHostAddress).Returns("127.0.0.1");
request.Object.Cookies.Add(new HttpCookie("erpstorevid")
{
Value = principal.VisitorId,
});
context.Setup(ctx => ctx.Request).Returns(request.Object);

// Sessions
var session = new Mock<HttpSessionStateBase>();
context.Setup(ctx => ctx.Session).Returns(session.Object);

// Server
var server = new Mock<HttpServerUtilityBase>();
server.Setup(s => s.MapPath(It.IsAny<string>())).Returns<string>(r => {
if (r.Equals("/bin", StringComparison.InvariantCultureIgnoreCase))
{
r = string.Empty;
}
var path = typeof(ERPStore.ERPStoreApplication).Assembly.Location;
var fileName = System.IO.Path.GetFileName(path);
path = path.Replace(fileName, string.Empty);
r = r.Trim('/').Trim('\\');
path = System.IO.Path.Combine(path, r);
return path;
});
context.Setup(ctx => ctx.Server).Returns(server.Object);

// Principal
context.Setup(ctx => ctx.User).Returns(principal);

// Items
context.Setup(ctx => ctx.Items).Returns(new Dictionary<string, object>());

return context;
}

Le principe est de faire un retour du type demandé pour chaque propriété et méthode, a l’issue un Context Http est retourné pret à l’emploi.


La critique portait au niveau de l’initialisation, ce qui a changé maintenant l’appel de classe ERPStoreApplication est fait au moment du initialize (simulation d’une requete http) qui est en quelque sorte le bootstapper d’ERPStore c’est lui qui a la responsabilité de configurer le container d’inversion de dépendance (Unity), que ce soit pour les tests ou en production il est appelé exactement de la même manière maintenant. Je pouvais aller plus loin encore en créant une instance de Global.asax et en appelant la méthode BeginRequest()


Maintenant pour tester un controller il suffit d’écrire sa propre classe qui doit heriter de TestBase, par exemple le login du site :


 

[TestFixture]
public class AccountControllerTests : TestBase
{
    [SetUp]
    public override void Initialize()
    {
        base.Initialize();
    }


    [TearDown]
    public void TearDown()
    {
        base.TeardownHttpContext();
    }



    [Test]
    public void Login()
    {
        var m_Controller = CreateController<ERPStore.Controllers.AccountController>();
        var result = m_Controller.Login() as System.Web.Mvc.ViewResult;
        Assert.AreEqual(result.ViewName, string.Empty);
    }


    [Test]
    public void Login_Form()
    {
        var accountController = CreateController<ERPStore.Controllers.AccountController>();


        var accountService = System.Web.Mvc.DependencyResolver.Current.GetService<ERPStore.Services.IAccountService>();
        var user = new ERPStore.Models.User();
        user.Login = "userName1";
        user.Id = 12345;
        accountService.SaveUser(user);


        accountService.SetPassword(user, "password1");


        var loginResult = accountController.Login("userName1", "password1", false, null) as System.Web.Mvc.RedirectToRouteResult;


        Assert.AreEqual(loginResult.RouteName, Routing.ERPStoreRoutes.ACCOUNT);
    }


}


La classe de base fournit le controller a tester grâce à la methode CreateController<…>()

  protected T CreateController<T>()
where T : System.Web.Mvc.Controller
{
var httpContext = GetHttpContext();
var result = CreateController<T>(httpContext);
return result;
}

protected T CreateController<T>(System.Web.HttpContextBase httpContext)
where T : System.Web.Mvc.Controller
{
var controller = m_Container.Resolve<T>();
controller.SetupControllerContext(httpContext);

return controller;
}
Grace a cette classe de base il est possible d’obtenir une couverture de 100% sur les controllers, il est meme possible de tester également les routes.
  [Test]
public void Cart_Href()
{
var ctrl = CreateController<ERPStore.Cart.Controllers.CartController>();

var url = ctrl.Url.CartHref();

Assert.AreEqual(url, "/panier");
}
avec sa methode d’extension
  public static string CartHref(this UrlHelper helper)
{
return helper.RouteERPStoreUrl(Cart.Routes.CART);
}
et son enregistrement
   routes.MapERPStoreRoute(
Routes.CART
, "panier"
, new { controller = "Cart", action = "Index", id = string.Empty }
, namespaces
);
 
Bons tests à tous

Asp.net MVC4 Web Api et Unity

 

Je suis en train de migrer un certain nombre de service pour utiliser Web Api, j’utilise au quotidien Unity comme container pour tous mes services. Voici comment utiliser un Inverseur de controle comme Unity avec Asp.Net MVC4 :

image

Dans on premier temps il faut sélectionner un projet de type Web Api

image

Puis ajouter Unity en utilisant NuGet, la dernière version est la 2.1

l’ApiControlleur  fourni par défaut avec le nouveau projet est le suivant :

   1:      public class ValuesController : ApiController
   2:      {
   3:          // GET /api/values
   4:          public IEnumerable<string> Get()
   5:          {
   6:              return new string[] { "value1", "value2" };
   7:          }
   8:   
   9:          // GET /api/values/5
  10:          public string Get(int id)
  11:          {
  12:              return "value";
  13:          }
  14:   
  15:          // POST /api/values
  16:          public void Post(string value)
  17:          {
  18:          }
  19:   
  20:          // PUT /api/values/5
  21:          public void Put(int id, string value)
  22:          {
  23:          }
  24:   
  25:          // DELETE /api/values/5
  26:          public void Delete(int id)
  27:          {
  28:          }
  29:      }

Nous ajoutons un constructeur dans lequel nous allons passer le service comme ceci :


   1:      public class ValuesController : ApiController
   2:      {
   3:          public ValuesController(Services.IValueService valueService)
   4:          {
   5:              ValueService = valueService;
   6:          }
   7:   
   8:          protected Services.IValueService ValueService { get; private set; }
   9:   
  10:          // GET /api/values
  11:          public IEnumerable<string> Get()
  12:          {
  13:              return ValueService.GetValues();
  14:          }
  15:   
  16:          // GET /api/values/5
  17:          public string Get(int id)
  18:          {
  19:              return ValueService.GetValueById(id);
  20:          }
  21:   
  22:          // POST /api/values
  23:          public void Post(string value)
  24:          {
  25:              ValueService.Save(value);
  26:          }
  27:   
  28:          // PUT /api/values/5
  29:          public void Put(int id, string value)
  30:          {
  31:              var v = new KeyValuePair<int, string>(id, value);
  32:              ValueService.Save(v);
  33:          }
  34:   
  35:          // DELETE /api/values/5
  36:          public void Delete(int id)
  37:          {
  38:              ValueService.Delete(id);
  39:          }
  40:      }

Voici le détail du service (simpliste) :


   1:      public class ValueService : IValueService
   2:      {
   3:          private Dictionary<int, string> m_Values;
   4:   
   5:          public ValueService()
   6:          {
   7:              m_Values = new Dictionary<int, string>()
   8:              {
   9:                  { 1 , "value1" }, 
  10:                  { 2 , "value2" },
  11:              };
  12:          }
  13:   
  14:          public IEnumerable<string> GetValues()
  15:          {
  16:              return m_Values.Select(i => i.Value);
  17:          }
  18:   
  19:          public string GetValueById(int Id)
  20:          {
  21:              var value = m_Values.SingleOrDefault(i => i.Key == Id);
  22:               if (value.Key != null)
  23:              {
  24:                  return value.Value;
  25:              }
  26:              return null;
  27:          }
  28:   
  29:          public void Save(string value)
  30:          {
  31:              m_Values.Add(m_Values.Count + 1, value);
  32:          }
  33:   
  34:          public void Save(KeyValuePair<int, string> v)
  35:          {
  36:              m_Values.Add(v.Key, v.Value);
  37:          }
  38:   
  39:          public void Delete(int id)
  40:          {
  41:              m_Values.Remove(id);
  42:          }
  43:      }

Maintenant si nous appelons le service directement voici le résultat :


image


<ExceptionType>System.InvalidOperationException</ExceptionType>

<Message>

An error occurred when trying to create a controller of type 'UnityMvcApplication.Controllers.ValuesController'. Make sure that the controller has a parameterless public constructor.

</Message>

<StackTrace>

Nous allons donc faire de telle sorte que Unity vienne injecter le service attendu dans le constructeur, pour cela il faut configurer unity dans la methode app_start de l’application comme ceci :

   1:          protected void Application_Start()
   2:          {
   3:              AreaRegistration.RegisterAllAreas();
   4:   
   5:              RegisterGlobalFilters(GlobalFilters.Filters);
   6:              RegisterRoutes(RouteTable.Routes);
   7:   
   8:              var container = new Microsoft.Practices.Unity.UnityContainer();
   9:   
  10:              // Mapping des services pour Web Api
  11:              container.RegisterInstance<System.Web.Http.HttpConfiguration>(System.Web.Http.GlobalConfiguration.Configuration);
  12:              container.RegisterType<System.Web.Http.Dispatcher.IHttpControllerFactory, System.Web.Http.Dispatcher.DefaultHttpControllerFactory>();
  13:              container.RegisterType<System.Web.Http.Dispatcher.IHttpControllerActivator, System.Web.Http.Dispatcher.DefaultHttpControllerActivator>();
  14:              container.RegisterType<System.Web.Http.Common.ILogger, Services.ServiceLogger>();
  15:              container.RegisterType<System.Web.Http.Controllers.IHttpActionSelector, System.Web.Http.Controllers.ApiControllerActionSelector>();
  16:              container.RegisterType<System.Web.Http.Controllers.IHttpActionInvoker, System.Web.Http.Controllers.ApiControllerActionInvoker>();
  17:              container.RegisterType<System.Web.Http.Controllers.IActionValueBinder, System.Web.Http.ModelBinding.DefaultActionValueBinder>();
  18:              container.RegisterType<System.Web.Http.Metadata.ModelMetadataProvider, System.Web.Http.Metadata.Providers.CachedDataAnnotationsModelMetadataProvider>();
  19:              container.RegisterType<System.Net.Http.Formatting.IFormatterSelector, System.Net.Http.Formatting.FormatterSelector>();
  20:              System.Web.Http.GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
  21:                  (Type serviceType) =>
  22:                  {
  23:                      return container.Resolve(serviceType);
  24:                  },
  25:                  (Type serviceType) =>
  26:                  {
  27:                      return container.ResolveAll(serviceType);
  28:                  });
  29:   
  30:              // Mapping du service des valeurs pour la demo
  31:              container.RegisterType<Services.IValueService, Services.ValueService>();
  32:   
  33:              BundleTable.Bundles.RegisterTemplateBundles();
  34:          }

lors du même appel Web Api le résultat est le suivant, le service à bien été injecté dans le constructeur  :


image


Explications, le service Web Api pour fonctionner avec Unity à besoin qu’un certain nombre de services du framework soient déclarés :

			container.RegisterType<System.Web.Http.Dispatcher.IHttpControllerFactory, System.Web.Http.Dispatcher.DefaultHttpControllerFactory>();
container.RegisterType<System.Web.Http.Dispatcher.IHttpControllerActivator, System.Web.Http.Dispatcher.DefaultHttpControllerActivator>();
container.RegisterType<System.Web.Http.Common.ILogger, Services.ServiceLogger>();
container.RegisterType<System.Web.Http.Controllers.IHttpActionSelector, System.Web.Http.Controllers.ApiControllerActionSelector>();
container.RegisterType<System.Web.Http.Controllers.IHttpActionInvoker, System.Web.Http.Controllers.ApiControllerActionInvoker>();
container.RegisterType<System.Web.Http.Controllers.IActionValueBinder, System.Web.Http.ModelBinding.DefaultActionValueBinder>();
container.RegisterType<System.Web.Http.Metadata.ModelMetadataProvider, System.Web.Http.Metadata.Providers.CachedDataAnnotationsModelMetadataProvider>();
container.RegisterType<System.Net.Http.Formatting.IFormatterSelector, System.Net.Http.Formatting.FormatterSelector>();

 

J’ai trouvé pour chacun une implémentation concrète sauf pour ILogger, si quelqu’un sait ou se trouve une implémentation dans le framework, pour l’instant j’ai du créer une classe qui implémente l’interface.

une fois tous les service déclarés “mappé” avec Unity il suffit d’indiquer un resolver pour Web Api, ce mecanisme avait déjà été initié avec MVC3 et son DependencyResolver.

			System.Web.Http.GlobalConfiguration.Configuration.ServiceResolver.SetResolver(
(Type serviceType) =>
{
return container.Resolve(serviceType);
},
(Type serviceType) =>
{
return container.ResolveAll(serviceType);
});

la c’est très bien fait, il n’y a que 2 methodes à declarer comme pour le DependencyResolver , Resolve et ResolveAll, a la fin on oublie pas de déclarer également le service des valeurs :

			container.RegisterType<Services.IValueService, Services.ValueService>();
Ci dessous le code source de cet exemple :