16.10.2019 / Nhu Kangasniemi

This article is a follow-up blog from my previous one for authentication with Azure AD in the front-end.

Link to post: https://www.bilot.fi/authentication-with-azure-ad-using-msal-react-app/

 

Src: Microsoft Documentation

 

Above is the process of securing your web app and web APIs using Azure AD. First, you need to register your Web APIs with Azure to make sure that it doesn’t allow anonymous requests. User then logins to authenticate him/herself and requests access token from Azure AD. Azure AD will provision access token for authenticated users, then you write codes to attach token to header before users call any APIs.

In your React app,  create a separate file for calling APIs, then import msalApp from ‘auth-utils’. msalApp is an object instance of UserAgentApplication, which comes with the built-in methods like getAccount() and acquireTokenSilent().  GetAccount() returns the account object, which contains account info, after user successfully login. Check if there is account info, then call acquireTokentSilent to acquire access token from cache or from hidden frames if not available before every call to API. Last but not least, attach the token in your request header.

 

import axios from 'axios'
import { msalApp, GRAPH_REQUESTS } from './auth-utils'
//Call AcquireTokenSilent to acquire token
async function getToken() {
  // grab current state
  const account = await msalApp.getAccount()
  const token =
    account && (await msalApp.acquireTokenSilent(GRAPH_REQUESTS.LOGIN))
  return {
    headers: {
      Authorization: `Bearer ${token.accessToken}`, // the token is a variable which holds the token
    },
  }
}
export const get = async (path, params = {}) => {
  const item = await getToken()
  return axios.get(`${BASE_URL}${path}`, item, params).then(res => res.data)
}
export const getUserInfo = () => {
  return get(`User`)
}

 

For further instruction on how to secure your APIs in Azure using OAuth 2.0 protocol, please follow the link here:

https://docs.microsoft.com/en-us/azure/api-management/api-management-howto-protect-backend-with-aad


2.09.2019 / Lasse Ruokolainen


AI-core on kehittämämme koneoppimis-infrastruktuuri, joka koostuu valtavasta kokoelmasta geneeristä, uudelleen käytettävää koodia. Olemme kehittäneet sen, koska halusimme kyvykkyyttä viedä AI-projekteja läpi nopeammin ja samalla minimoida ohjelmointivirheet. Lisäksi, samojen asioiden koodaaminen uudelleen ja uudelleen on aika pöljää ja myös melko tylsää. Meistä tuntui myös siltä, että useiden AI/ML-ympäristöjen ylläpito ja kehitys vaatii koherentin ratkaisun, joka taipuu useisiin eri liiketoimintaongelmiin (esim. IoT, asiakasanalytiikka, laadunvalvonta jne.).

Kuten yllä mainittiin, Bilotin AI-core on käytännössä koodikokoelma, joka mahdollistaa robustin koneoppimisratkaisujen kehittämisen ja tuotannollistamisen. Ratkaisumme integroi datan hallinnan ja esikäsittelyn, virheiden hallinnan ja lokituksen, mallien opettamisen ja versioinnin, mallien soveltamisen ja julkaisun. Mikä parasta, kaikkea tätä toiminnallisuutta hallitaan rajallisella määrällä koodia ohjaustiedostojen muodossa.

Mitkä tarkalleen ottaen ovat AI-coren hyödyt? Meidän mielestämme ainakin seuraavat:

  1. Se nopeuttaa AI/ML kehitystä merkittävästi, koska koodi on (enimmäkseen) valmiiksi olemassa. Tämä minimoi suoraan koodausvirheiden riskin ja poistaa turhan iteraation.
  2. Se tarjoaa yhtenäisen rakenteen useiden eri koneoppimisongelmien (busineksen näkökulmasta).
  3. Koska koodi on täysin avointa, se mahdollistaa käyttäjälle loputtomasti joustavuutta muokata toiminnallisuutta haluamallaan tavalla.

Sen lisäksi että AI-core on toiminnallisesti kattava ja joustava, se voidaan ottaa käyttöön käytännössä missä tahansa ympäristössä; tämä riippuu täysin käyttäjän/asiakkaan preferensseistä. Käyttöönotto on myös suhteellisen vaivatonta, riippumatta siitä onko kyseessä lokaali tietokone, virtuaalikone/palvelin tai pilvialusta.

Erityisesti pilviversio yhdistelee usean eri state-of-the-art teknologian kyvykkyyksiä. Mallit koulutetaan H2O:n API:lla, hallitaan MLflow:n API:lla ja koko komeus lepää Databricks:in päällä Azuressa. Kiinnostavaa? Jännää? Mahtavaa? Niin meistäkin. Siksi koostimme AI-asiaa omalle sivustolleen. Lue lisää: bilot.ai.


21.03.2019 / Esa Vanhanen-Varho

Haven’t really needed to change Logic App parameters without doing a new deployment earlier, but now I had an interesting problem.

I tried to create my first recursive Logic App. Naturally at that point had forgotten that I can solve my problem also with do-while-loop, so recursion is not the main point here – the Logic App’s parameter setting without running ARM deployment is – if you’re interested more in recursion, here are a couple of good posts by Vincent-Philippe Lauzon and François Boucher.

I did my experiment with the latter post’s Method 2 – calling the same Logic App directly with HTTP action pointing to own request URL. You can manually add the URL easily, but how to deploy a new instance with ARM template where circular references are not allowed and listCallbackUrl function is not working…

So the workflow without correct URL is here – it would be easy to save and copy the value from request trigger, but that’s not a way to automate deployment. (Remember to make sure your recursion really works correctly before actually executing it…)

If I try to deploy this from an ARM template that would try get own CallbackUrl like this:

It would only fail miserably:

So, go with parameters…create a Logic App parameter with a placeholder value:

Logic App look now like this:

 

After deployment, Powershell solves the rest:

  1. Get original settings:

    $lapp = Get-AzureRmLogicApp -ResourceGroupName TempLA -Name RecursiveArmTest

  2. Get deployed Logic App’s callback url:

    $newurl = Get-AzureRmLogicAppTriggerCallbackUrl -ResourceGroupName TempLA -Name RecursiveArmTest -TriggerName request

  3. Set Logic App parameter value to deployed callback url from previous step:

    $lapp.Parameters[‘plaSelfUrl’].Value = $newUrl.Value

  4. Update Logic App:

    Set-AzureRmLogicApp -ResourceGroupName TempLA -Name RecursiveArmTest -Parameters $lapp.Parameters

And that’s it – easy to set in your pipeline too (you could actually get the callbackUrl as an output from deployment too without separate PS command). And seemed to work:

The best part of this is that you don’t have to run an ARM template deployment to change those Logic App parameters – which might be very useful for example in updating some API keys in multiple Logic Apps etc…Didn’t find any post around the topic, so maybe this helps someone else too.

ARM templates can be downloaded from this link.


24.11.2018 / Michał Schneck

Targi branżowe są dla każdej firmy jednym z ważniejszych wydarzeń w ciągu roku. Wymagają profesjonalnych przygotowań. Nie dziwi więc fakt, że firmy przykładają do nich dużą wagę i starają się je wykorzystać jak najefektywniej.

Targi są świetną okazją do pozyskania nowych klientów. Nasi handlowcy zazwyczaj wracają z takich eventów z pełnym wizytownikiem, który jest bazą do dalszych działań sprzedażowych.

Być może warto spróbować innego, nowocześniejszego podejścia.  Pomoże w tym system SFA/CRM. Ułatwi on zbudowanie pozytywnego wizerunku, a praca z leadem stanie się bardziej efektywna.

Warto zaprezentować jak SAP Sales Cloud (w skrócie C4C) może pomóc w pozyskaniu nowych klientów na targach i innych eventach.

Lead w zasięgu ręki, a raczej naszego skanera CRM

W SAP C4C wystarczy, że handlowiec za pomocą opcji „Skanuj” na swoim tablecie bądź smartfonie zrobi zdjęcie otrzymanej wizytówki. System automatycznie, przy wykorzystaniu technologii OCR, rozpozna i uzupełni Imię i Nazwisko potencjalnego leada oraz pozostałe dane teleadresowe.

Co ważne, przed jego utworzeniem w systemie, C4C może sprawdzić czy w naszej bazie nie istnieją już potencjalne duplikaty w postaci leadów, osób kontaktowych lub klientów. Nasz handlowiec już podczas wprowadzania informacji wie czy ktoś wcześniej pracował z danym klientem. Może również przejrzeć historię działań sprzedażowych lub w wygodny sposób przypisać nowe kontakty do istniejącego już w CRM klienta.

Warto odnotować, że podczas tworzenia nowego leada, można pozyskać odpowiednie zgody marketingowe, przez co oszczędza się czas pracowników działu marketingu i przyspiesza kolejne akcje skierowane do potencjalnego klienta.

Dzięki regułom routingowym C4C może przekazać leada od razu do odpowiedzialnej osoby np.  kolegi z zespołu sprzedażowego lub osoby odpowiedzialnej za dany obszar sprzedaży (sales territory).

Na leadzie możemy również udostępnić jedną lub wiele ankiet, które pozwolą handlowcowi doprecyzować informacje o obszarze zainteresowań klienta, i co najważniejsze, w czasie rzeczywistym udostępnić te dane wszystkim uprawnionym użytkownikom systemu CRM.

Poniżej przykład ankiety dotyczącej potencjału klienta:

Analityka – raportowanie

Dane można analizować i uzupełniać w czasie trwania targów lub po ich zakończeniu.

W przypadku wydarzeń wielodniowych, jeszcze w czasie ich trwania, handlowiec lub manager może utworzyć wstępne spotkania z potencjalnymi klientami, przesłać dodatkowe informacje  czy stworzyć potencjalne szanse sprzedaży.

Dzięki wykorzystaniu takiego podejścia oraz wsparcia w postaci C4C, możemy w prosty sposób pozyskać dane na temat:

– liczby klientów obecnych na targach,

– potensjalnych klientów,

– przychodu wygenerowanego z danego wydarzenia,

– zysku z konkretnego eventu w stosunku do innych targów.

 

Skaner CRM to nowoczesne narzędzie, które warto wdrożyć w swojej organizacji. Koniec ze żmudnym poszukiwaniem wizytówek, potencjalnych klientów oraz czasochłonnym wprowadzaniem danych do systemu. Dzięki skanerowi CRM praca jest szybsza, efektywniejsza i pozwala skupić się na kluczowych zagadnieniach sprzedażowych. Jeśli to narzędzie Państwa zainteresowało, zapraszamy do kontaktu z nami.

 

 

 

 


13.11.2018 / Esa Vanhanen-Varho

I needed to make a small change to an old Azure function, and ended up tinkering a bit on how to automate the deployment process with some of the latest options. And I just fell in love with Azure (DevOps) Pipelines & Azure Functions Run-from-Package functionality.

I don’t consider myself an expert on Azure DevOps (also formerly known as Visual Studio Team Services = VSTS or Visual Studio Online = VSO) – quite the opposite, as I usually have the possibility to ask from real experts. But this time I just started experimenting a bit. An old Azure function used to implement a complex integration interface against a SaaS system needed a new feature. In the early days we hadn’t created automation, mostly because the customer didn’t at the time have their own VSTS tenant, and things were busy at the time – so we decided to postpone this, but now…

The rest of this blog goes to technical “details”, but the key message is: automating deployments is very easy with Azure DevOps! Even if you are just a beginner as the default templates are a good starting point! Easy way to save your nerves (and yours or your customer’s money with every future deployment).

Azure Function Versioning

First of all I wanted to make the version numbering automated to be able to check easily which version I’m running. There are many ways to achieve this, but I’ve been using GitVersion lately because it gives possibility to use Semantic Versioning – and mostly to be able to bump version numbers with commit messages without extra manual work. I started using GitVersion with Logic App ARM templates after I saw Teemu Tapanila’s presentation at IglooConf 2018 (link at the end) because it just seemed to fit the purpose well. 

This function project was created before that presentation, so first question was how difficult would it be to include it later to the v1 function project. Well…not difficult at all. Basically I just followed documentation and ran one package manager command:

Install-Module GitVersionTask

…and that’s it. I added the CheckVersion function below to my app to verify this:

    public static class CheckVersion
    {
        [FunctionName("CheckVersion")]
        public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
        {
            string productVersion = FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion;
            return req.CreateResponse(HttpStatusCode.OK, "Function version: " + productVersion);
        }
    }

And the result started looking good:

“Function version: 1.2.0-alpha.3+Branch.dev.Sha.420e006df651a45cca1c3a903af03bb25dc27b7f”

Azure DevOps Build Pipeline

Originally this v1 function was deployed with Function App internal deployment. It checked repository for changes and started building if changes were committed to certain branches. But I wanted to try to make this deployment as quick as possible and easy to roll back, so the run-from-package option was the way to go.

So – first I needed to create build pipeline that creates zip package that can be then used in release.

And I just created a new build pipeline with the “Use the visual designer” option, chose my repository and branch, and chose the ready C# Function template and…basically, that’s it.

Just added the GitVersion task (already had it installed from the Marketplace) with default variables, although I noticed that it’s not even needed as the version I installed to the project also updates the version number in pipeline.

Then I got another idea – should I also have a debug build available – for example to deploy that to dev & test environments and release version with less traces to production. Or have the possibility to change to debug build if necessary to debug remotely. And another surprise for me how easy this was.

First, add wanted configurations to BuildConfiguration variable…

..then add a variable reference to Pipeline Multiplier field after selecting “Multi-configuration” from above:

…and finally change the package naming in the Archive Files task:

And now both packages are published to the same artifact:

After the build pipeline ran (two builds), the artifact contents were just like I wanted:

Now I decided to tweak a bit more with the build number to have a bit more info than the semantic version like “1.2.0+4”. So I added a PowerShell Script task to run the following Inline-script to add repository name, date and BuildId (mostly for this pipeline debugging purposes) to the final Build Number.

So basically this out-of-the-box pipeline worked for build.

Deploying with Azure DevOps Release Pipeline

And again I just started with a new release pipeline and added an empty stage for dev environment:

Then I linked the build artifact and gave it a shorter alias…

Originally I used two separate tasks, Azure File Copy and Azure CLI. But as the CLI command prompt is not very good with variables, I decided to combine both tasks to a Azure PowerShell script that is more familiar to me. I think bash could also work well, must try it another time. (I’ve been trying to quit command prompt after my EDIFACT years a long, long time ago – after once triggering about 3000 prompt windows by accidental error in script before server ran out of memory…)

First I set up some variables to be used in the pipeline.

And then some stage dependent variables related to the Function App to Variable Groups (not going into those details here), so in final pipeline I can have all environments with the same task but link variables to selected group in that stage. Had to hide these function

And then I added the actual PowerShell script task, with some inline code…

 

The main steps in the script are:

  • Connect to storage
  • Upload build zips
  • Create SAS URIs with read-only access
  • Update Function’s AppSettings with new blob links

And the actual script to do the magic is below (Download):

$conf = "$(configToRun)"
### Connect to storage
$ctx = (Get-AzureRmStorageAccount -ResourceGroupName $(ZipStorageRG) -Name $(ZipStorageName)).Context

### Enter source dir
Set-Location $(System.DefaultWorkingDirectory)/_func/Some.Functions.AppName

### Upload blobs
$blobDbg = "$(Release.Artifacts._func.BuildNumber)/$(Release.ReleaseName)/debug.zip"
$blobRel = "$(Release.Artifacts._func.BuildNumber)/$(Release.ReleaseName)/release.zip"
Set-AzureStorageBlobContent -File .\debug.zip -Container $(ZipContainerName) -Blob $blobDbg -Context $ctx
Set-AzureStorageBlobContent -File .\release.zip -Container $(ZipContainerName) -Blob $blobRel -Context $ctx

### Create SAS URIs
$endTime = (Get-Date).AddYears(100)

$uriRel = (New-AzureStorageBlobSASToken -Context $ctx -Container $(ZipContainerName) -Blob $blobRel -Permission r -Protocol HttpsOnly -ExpiryTime $endTime -FullUri).ToString()
$uriDbg = (New-AzureStorageBlobSASToken -Context $ctx -Container $(ZipContainerName) -Blob $blobDbg -Permission r -Protocol HttpsOnly -ExpiryTime $endTime -FullUri).ToString()

### Update Function AppSettings
### Get current settings first
$webApp = Get-AzureRmWebApp -ResourceGroupName $(varFuncRG) -Name $(varFuncAppName)
$oldAppSettings = $webApp.SiteConfig.AppSettings

### Copy existing settings to new hashtable
$newAppSettings = @{}
ForEach ($s in $oldAppSettings)
{
$newAppSettings[$s.Name] = $s.Value
}

### Set new zip values
$newAppSettings["WEBSITE_RUN_FROM_ZIP_DBG"] = $uriDbg
$newAppSettings["WEBSITE_RUN_FROM_ZIP_REL"] = $uriRel

if($conf.ToLower() -eq "debug")
{
  $newAppSettings["WEBSITE_RUN_FROM_ZIP"] = $uriDbg
}
else
{
  $newAppSettings["WEBSITE_RUN_FROM_ZIP"] = $uriRel
}

### Finally store values
Set-AzureRmWebApp -ResourceGroupName $(varFuncRG) -Name $(varFuncAppName) -AppSettings $newAppSettings

Naturally after trying the Az CLI way, I forgot to read the old settings first and ended up deleting all existing values. This step could be also done with ARM template in a safer way.

But that’s it – after running dev stage, my Function App showed nicely the new settings and the CheckVersion function visible (and returning the same SemVer number that was generated in build phase). Having those both settings ready helps a lot if you want to change between release and debug at some point.

And the storage looked like this – the path tells it all. In final pipeline I’ll probably leave the release number out, but here it just helped with testing a lot.

For the first try I was happy with the results. Now it’s just a matter of making this even more useful with our real Azure DevOps experts. Hopefully someone gets the same inspiration as I did and starts learning. Don’t think I’ll ever use any other method to deploy my functions…

References & more information:


31.08.2018 / Arto Pihlaja

Tänä keväänä Bilotin ja Louhian asiantuntijat venyttivät päiväänsä ja käyttivät vapaa-aikansa BilotGo.ai hackathon-kisassa. Olin mukana yhdessä tiimissä – siinä joka lopulta onnekkaasti voitti kilpailun. Tässä blogissa kerron ajatukseni siitä, minkä seikkojen ansiosta onnistuimme. Uskon että ne pätevät muihinkin analytiikka- ja tietojärjestelmäprojekteihin.

1. Oikean kysymyksen tunnistaminen

Olemme varmaan kaikki kuulleet innostavia esimerkkejä tekoälyn ja koneoppimisen käytöstä. Usein nuo esimerkkitapaukset ovat kuitenkin vuosien määrätietoisen työn tuloksia. Tilaajalla pitää olla näkemys siitä, miten tekniikkaa hyödynnetään liiketoiminnassa, mutta tavoitetta kohti edetään pienin askelin. On paljon helpompaa päättää ensin pilotista ja sitten mahdollisista seuraavista iteraatioista kuin hakea hyväksyntää vuosia kestävälle, miljoonien eurojen investointiohjelmalle. Rajauksia joutuu tekemään toteutuksenkin aikana, mutta joka vaiheen tulosten pitää silti olla hyödyllisiä.

kuvalähde: ligonier.org

Hackathonissa käytimme työn tilaajan kanssa paljon aikaa sopivan tehtävän tunnistamiseksi ja rajaamiseksi. Meidän piti tunnistaa kysymys, jonka vastauksesta olisi selvää hyötyä liiketoiminnassa, ja joka olisi ratkaistavissa käytettävissä olevilla tiedoilla ja ajalla. Aluksi ryhdyimme selvittämään lehmien ruokinnan vaikutusta maidon määrään ja laatuun, mutta työn edetessä jouduimme määrittelemään kysymyksen uudelleen. Kisassa päädyimme ennustamaan maidon määrää lehmän iän ja poikimisten perusteella ja jätimme muut kysymykset jatkoprojekteihin.

 

2. Tiedon kerääminen

Kun kysymys on selvä, kerätään vastauksen selvittämiseen tarvittavat tiedot. Varsinkin alussa työ voi olla vuorottelua kysymyksen määrittelyn ja tiedon etsimisen välillä, sillä tiedon määrä ja laatu eivät aina vastaakaan käsityksiä.

Hackathonissa ryhdyimme tekemään ennustavaa mallia esimerkkitiedostojen perusteella. Vasta kisan puolivälin jälkeen osoittautui, että nuo tiedostot oli koottu käsin yksittäisistä lähteistä. Varsinaisen aineiston rakenne poikkesi esimerkeistä täysin ja mikä pahinta, tieto ei ollut riittävän kattavaa. Palasimme siis määrittelyyn. Sovimme myös, että kisan jälkeen teemme suunnitelman tiedon keräämiseksi ja jalostamiseksi.

 

3. Tiedon valmistelu

Yleisesti sanotaan että koneoppimisprojektissa ainakin 80 % työstä on tiedon valmistelua ja alle 20 % ennustavan mallin kehittämistä. Näin oli tässäkin projektissa – toteutusvaiheen osalta! Kun otetaan huomioon määrittely ja julkaisun valmistelu, algoritmien soveltamiseen käytetyn ajan osuus jäi vielä selvästi pienemmäksi.

Keskeisin osa datastamme oli roboteista saatuja mittaustuloksia, joten sen luulisi olevan määrämuotoista ja johdonmukaista. Käytännössä kuitenkin robotit olivat erilaisia ja tuottivat eri muotoista dataa. Sen lisäksi poikkeavien tulosten tulkinta oli vaikeaa. Esimerkiksi kun maidon rasvapitoisuus oli 30 %, kyseessä oli varmasti virhe, mutta olivatko 6 % ja 12 % välillä olevat arvot? Tiedon valmistelu edellyttää sen merkityksen syvää ymmärrystä. Siksi teimmekin sitä tiiviissä yhteistyössä tilaajan kanssa.

kuvalähde: Raisio Oyj

4. Julkaisu

Upeakin toteutus jää turhaksi, jollei kohdeyleisö omaksu sitä.

Hackathon-kisamme päättyi siihen, että toteutukset esiteltiin ulkopuolisista asiantuntijoista kootulle tuomaristolle. Niinpä tiimimme omistikin kahdeksan viikon kokonaisajasta yli viikon käyttöliittymän parantamiseen ja loppudemon valmisteluun. Mietimme esityksen kantavan tarinan ja karsimme sisältöä, jotta ratkaisu ja sen hyödyt korostuisivat. Kuten valmentajamme Antti Apunen meitä neuvoi: kohdeyleisöä ei kiinnosta, mihin algoritmiin toteutus perustuu. He luottavat siinä meidän asiantuntemukseemme ja haluavat vain nähdä tulokset ja hyödyn. Kun sisältö oli mietitty, harjoittelimme sen esittämistä toiminto toiminnolta ja jopa sanasta sanaan.

Hackathon päättyi vartin mittaisiin esityksiin, mutta muissakin projekteissa varsinainen julkaisuhetki on lyhyt ja ratkaiseva, oli sitten kyse sisäisen järjestelmän käyttöönotosta tai verkkopalvelun julkaisusta. Kuluttajat harvoin antavat toista mahdollisuutta, eikä ammattikäyttäjienkään kannata olettaa olevan pitkämielisiä. Ratkaisun hyödyn pitää nousta selkeästi esille, ja käytön pitää näyttää helpolta. Siispä projektin loppuvaiheessa täytyy malttaa lopettaa teknisten ominaisuuksien täydentäminen ja panostaa aikansa julkaisuun. Kun julkaisu onnistuu, ratkaisua voi hyvin täydentää seuraavissa iteraatioissa.

Uskon, että hackathonissa viimeistelty esityksemme lopulta ratkaisi kisan, ja palkitsi siten viikkojen uurastuksen. Samoin uskon, että projektin kuin projektin viimeistely varmistaa hyödyt.

Lisää BilotGo.ai-hackathonin ideasta täällä ja kisaamisesta täällä. Esittelemme muiden joukkueiden kanssa hackathonin tuloksia tänä torstaina tapahtumassamme – olethan tulossa?

kuvalähde: jonwilma.com

27.03.2018 / Mika Tanner

Mitä työntekijä toivoo työpaikaltaan ja -uraltaan?

Se riippuu usein monesta asiasta. Työuraansa aloittelevalla on luultavasti aika lailla eri perspektiivi kuin urallaan jo edenneellä, ja asiantuntijatehtävissä olevalla (tai tällaisia tavoittelevalla) on ehkä erilaiset odotukset tulevasta työpaikasta kuin vaikkapa myynnin, markkinoinnin, päällikön, johtajan tai assistentin roolissa olevilla.

Näinä aikoina työnantajan pitää kyetä esittämään hyvin monipuolinen arvolupaus. Yhtiö voi suoraan vaikuttaa kuitenkin vain osaan niistä tekijöistä, jotka vaikuttavat työnhakijan päätöksentekoon: kilpailukykyiseen kompensaatioon, erinomaisiin työsuhde-etuihin, kiinnostaviin työtehtäviin, pitkän aikavälin urapolkuihin tai vaikkapa tuottavuutta parantaviin työolosuhteisiin ja työpaikkaviihtyvyyteen.

Kaikkeen yrityskään ei voi suoraan varautua. Työnhakijan päätöksenteon kannalta isossa roolissa ovat myös esimerkiksi työpaikan inspiroiva ilmapiiri, voimaannuttava kulttuuri ja kiinnostavat asiakkuudet. Nämä syntyvät ja muotoutuvat niin monien asioiden yhteisvaikutuksesta, että niihin voi olla vaikea suoraan vaikuttaa.

Moni työnhakija haluaa päästä työskentelemään organisaatioon, jossa on yksilönä aidosti mahdollisuus vaikuttaa asioihin, ei osaksi tuhansien tuotannontekijöiden korporaatiota, jossa oma ääni sekoittuu masiinan matalan taajuuden huminaan. Työnhakija miettii luultavasti myös yrityksen brändiä ja imagoa – parantaako uusi työpaikka oman ansioluettelon arvoa vai ei?

Työssä jaksaa paremmin, kun kokee tekevänsä jotain merkityksellistä ja edessä on sopivasti haastava ja innostava iso kuva, jota tavoitellaan aidosti yhdessä. Se voi olla kasvutarina, jota kukin pääsee kirjoittamaan. Se voi olla kansainvälistyminen, joka voi tarjota itse kullekin reittejä maailmalle. Se voi olla uraauurtavien uusien teknologioiden haltuunottoa ja niiden myötä valtavaa oppimista. Meillä se on tätä kaikkea ja paljon sellaista, jota emme voi vielä edes ääneen sanoa.

”Merkityksellä voi olla merkitystä”

Kilpailu kovista osaajista on kovempaa kuin moneen vuoteen. Tulikuuma työmarkkina on tällä hetkellä täysin työntekijän. Jotta työn tarjoaja saisi audienssin pitää olla takanaan menestystarina, edessään lupaava tulevaisuus, tähtäimenään jännittävä visio ja lisäksi mielellään joku erityinen ’purpose’. Yrityksen tarina pitäisi mieluummin kertoa vastaamalla kysymykseen ”Miksi me teemme tätä?” kuin ”Mitä me teemme?”.

Tämän ajan työntekijä on kuitenkin älykäs ja tietää, mikä häntä palkitsee pitkässä juoksussa. Luonnollisesti kompensaation pitää olla oikeudenmukainen, mutta työn sisältö, oppimismahdollisuudet, työkaverit ja elämän tasapaino muodostavat kompensaatiota vahvemman houkuttimen ja pitkäaikaisen sitoutumisen.

Ensimmäisen työpäivän persoonallisen ja runsaan aloituspaketin glamour hälvenee nopeasti, jos vastaanotto ja työpaikan kulttuuri ei resonoikaan aidosti työntekijän odotusten kanssa.

Olemme Bilotilla käsitelleet viimeisen puolen vuoden aikana satoja työhakemuksia, haastatelleet näistä rapiat satakunta, ja lopulta rekrytoineet kuluvan vuoden aikana 20 uutta työntekijää. Olemme hiukan jäljessä rekrytointitavoitettamme, joka on noin 45 tälle vuodelle – syyskuuhun mennessä.

Jonkun mielestä olemme nirsoja uusien työntekijöiden suhteen ja että meillä on kohtuuttomat valintakriteerit. Myönnettäköön, että vaatimustasomme on kova, mutta me olemme valioliigatason joukkue, ja olisi epäoikeudenmukaista kaikkia kohtaan, jos laskisimme rimaa – siitäkin huolimatta, että joukkueellamme on huutava pula uusista pelaajista.

Mitä me sitten odotamme hakijalta?

”Asenteen pitää olla kunnossa”

Sloganimme on We Stand For More. Ihan alkuun olisi hyvä sisäistää mitä tämä slogan tarkoittaa. Sillä on nimittäin oikeasti merkitystä. Me toivomme, että ammatillisten vaatimusten lisäksi työnhakijalla on erityisesti asenne kunnossa. Joskus pitää olla valmis kulkemaan se kuuluisa ”extra mile” ja venymään pieniin sankaritekoihin. Kun asiakkaat näkevät, miten me oikeasti välitämme, saamme rakennettua uskollisia asiakkuuksia.

Me olemme luottamusbusineksessa, ja asiakkaamme olettavat saavansa meiltä kovan osaamisen lisäksi vastuunkantoa, rohkeutta, reippautta, heittäytymistä, paineensietokykyä ja valtavasti positiivista energiaa. Eli siis ihan samoja ominaisuuksia, joita kollega odottaa toiselta.

Koska olemme alamme pioneereja, työmme on usein aika luovaa – me teemme asioita ensimmäisinä, ilman esimerkkejä ja ilman ennakkotapauksia. Näin ei tosin tietysti aina ole, vaan meidän pitää olla valmiita tuottamaan myös asiakkaiden liiketoimintajatkuvuuden kannalta virheetöntä ja ammattimaista palvelua. Innovaatio ja ylläpito ovat asiakkaille yhtä tärkeitä. Jälkimmäinen turvaa nykyisen liiketoiminnan kannattavuuden ja edellinen varmistaa tulevaisuuden kilpailukyvyn.

”Vähemmänkin kokenut pääsee pelipaikoille”

Valtaosa asiantuntijoistamme on kokeneita “senioreita”, mutta meillä kasvaa myös joukko uuden sukupolven lupaavia juniorilahjakkuuksia. Meidän vastuumme on kasvattaa heistä tulevaisuuden maalintekijöitä – nuoren asiantuntijan vastuulla on vain tehdä parhaansa ja heittäytyä rohkeasti peliin mukaan. Vähemmänkin kokenut asiantuntija pääsee pelipaikolle, jos tahtoa riittää, ja sieltähän sitä kokemusta saa: tekemällä paljon virheitä ja oppimalla niistä.

Koetko, että olet valmis ottamaan uuden haasteen vastaan?

Olit sitten nuori ja nälkäinen tulevaisuuden tekijä, hiukan kokeneempi kettu tai mielestäsi kaiken nähnyt konkari, kannattaa tutustua meihin. Vaikkei meillä juuri nyt olisikaan auki juuri sinulle sopivaa pelipaikkaa, kuulisimme mielellämme, mitä sinulla on meille kertoa itsestäsi. Joskus riittää, että olet hyvä tyyppi, jolla on potentiaalia.

Ilmoittaudu, jos haluat tehdä samoja juttuja kuin nytkin, mutta paremmin, ketterässä ja persoonallisessa työntekijöidensä omistamassa kasvuyhtiössä. Anna itsestäsi kuulua, jos haluat olla töissä, joissa pääset suoraan vaikuttamaan. Jos haluat olla oman onnesi seppä, meillä voi olla todellinen mahdollisuus siihen.


8.06.2016 / Markus Kuuranta

Se on täytetty! Vuoden ylityömaratonin jälkeen on aika huokaista syvään: uusi verkkokauppa on vihdoin julkaistu! Kun kuohuviini loppuu ja ensimmäisten live-viikkojen hienosäädöt on hoidettu, alkaa jostain hiipiä epäilyksen varjo. Mitäs tälle verkkokaupalle nyt pitäisi tehdä?

Tekninen ylläpito on useimmiten kunnossa, ja hyvä niin; ilman tekniikkaa ei verkkokauppaa ole olemassa. Harmillisen usein verkkokauppa kuitenkin nähdään vain teknisenä ratkaisuna, jossa serverit noin vain takovat rahaa ilman mitään panostusta palvelupuoleen. Menestyvä verkkokauppa on yhdistelmä teknistä toimivuutta ja jatkuvaa käyttökokemuksen suunnittelua.

Varsinkin kuluttajapuolella verkkokaupan vaatima kuva- ja tekstisisällön määrä on melkoinen. Jos kalenteritasolla tehtyä suunnitelmaa sisällön päivittämisestä ei ole vielä tehty, on nyt viimeistään tartuttava toimeen. Tuotekuvausten ohella verkkokaupan muu sisältö on hunajaa hakukonenäkyvyyttä ajatellen, jolloin jatkuvasti päivittyvä sisältö on halpaa markkinointia. Moni verkkokauppias pulttaakin kaupan kylkeen esimerkiksi tuotearvosteluja käsittelevän blogin. Tarvittavat kirjoitus- ja grafiikkatyöt voi ulkoistaa, joten kynnys sisältömarkkinointiin on matala.

Sisällöntuotannon näkökulmasta on myös hyvä varmistaa sidosryhmien kitkaton pääsy omaan osuuteensa verkkokaupan hallinnasta. Mikäli tuotekuvat tulevat tavarantoimittajilta, tuotedata sisältää ristiinmyynnin logiikkaa tai CMS-osuudet sisältävät yhteyksiä muuhun maailmaan, säästää ajantasaisella hallinnan käyttöliittymällä pitkän pennin.

Verkkokaupan statistiikka tarjoaa arvokasta tietoa asiakkaiden ostoprosessista, ja osaavissa käsissä siitä saadaan louhittua esiin ostokäyttäytymisen malleja ja arvokkaita lisämyynnin mahdollisuuksia. Tilastot kertovat kuitenkin ainoastaan toteutuneista klikeistä, eikä asiakkaiden käyttökokemuksen monimuotoisuus välity datasta.

Verkkokaupan laadun takaamiseksi ratkaisu on käyttökokemuksen seurantaohjelma. Tällöin asiakkaisiin ollaan säännöllisessä yhteydessä eri kanavien kautta, optimoiden kaupan toimintaa myyvämpään suuntaan toiminnan aikaisten kokemusten myötä. Kvantitatiivinen ja kvalitatiivinen tieto tukevat hyvin toisiaan: suunnittelutyö tuottaa joukon lupaavia ideoita, ja niiden toteutusta voidaan simuloida tilastoja vasten. Jatkotoimien tulee perustua aitoon tarpeeseen, eikä toiminnallisuuksia kannata tehdä vain siksi, että kilpailijallakin nyt sattuu olemaan.

Tyypillinen sisältöjen hienosäädön arviointitekniikka on A/B-testaus, jossa uutuuksia koeponnistetaan ensin pienellä asiakasryhmällä. Toimintatavan ilmeisin etu on antaa asiantuntevimman tahon – asiakkaiden – päättää ratkaisujen toimivuudesta, jolloin kannattavat ideat kuplivat esille ilman raskaita järjestelmäpäivityksiä. Digitaalisissa palveluissa onkin hyvä sisäistää, ettei verkkokauppa tule koskaan olemaan valmis.

Verkkokaupan laadukas ylläpito on teknisen haastavuuden päälle melkoinen ruljanssi – mutta kannattava sellainen. Tärkeintä joka tapauksessa on, että asioita tehdään suunnitelmallisesti, pohjautuen oman asiakaskunnan käyttäytymiseen. Jos tarvitset suunnittelussa apukäsiä, ota yhteyttä Bilotin ecommerce-osaajiin.


14.03.2016 / Mika Tanner

This year’s SAP Innovation Forum is behind us. Bilot took center stage and managed to attract the vast majority of the 600+ attendants to its Full-stack Commerce stand. Less visible to the general audience was the VIP Breakfast event we hosted before the actual keynote speeches rang out in the large auditorium.

This year’s breakfast plot was about bridging together three levels of reality:

  • The dynamics of digitalization and competitiveness
  • Business transformation and IT on a company level
  • Foresight into practical digital business

 

IMG_0735
Digitalization for Breakfast: Jani Puroranta, Turkka Keskinen, Mika Tanner & Pekka Ala-Pietila

 

Pekka Ala-Pietilä (member of SAP SE Supervisory Board) took a stab at the first topic from a macrosystem perspective to provide the breakfast plot with a suitable high-level framework. The winners of the digital game are those who understand the dynamics of the ecosystem and the power of the platform.

“The winner is the one that is the fastest and most adaptable to change.” – Charles Darwin

Industries are converging, time-to-profit is accelerated and the leadership paradigm is shifting. The engine of growth consists of four cylinders (user experience, compelling business model, technological superiority and cost competitiveness) where the combustion of innovation as the fuel. The dynamics of competition is played on either a vertical dimension or a horizontal. Ala-Pietilä wrapped up his insightful narrative with a clear call-for-action. For the ecosystem to have opportunities to develop and grow, the market must invest in development to generate a pull effect. Sufficient suction to pull innovation out of the ecosystem into the market and into use.

With this excellent back-drop, Turkka Keskinen (CIO of Biofore giant UPM) described how business transformation and digitalization co-exist. UPM’s ten year transformation has been staggering. It has reshaped itself from and integrated paper company to a collection of growing new businesses. By doing so, the company managed to defer the decline in revenues, double its operating income, halve its net debt, nearly double its productivity and exceed its long-term return targets in nearly all six businesses. Keskinen structured UPM’s IT strategy with an Ironman analogy – The Triathlon. The three disciplines are Build, Run and Transform.

“IT supports Biofore by Digiforce” – Turkka Keskinen

IT has an essential role in UPM’s business development, IT forms the backbone for business operations and it is an important cornerstone in implementing strategy. IT must be able to provide a coherent framework for the development of capabilities which provides maximum business continuity, ensures efficient portfolio practices and doesn’t compromise agility. IT development fundamentals didn’t have to be reinvented: doing things right and doing the right things.

Bilot’s Jani Puroranta (Head of an Amazing Offering) took a very practical stance and illustrated by means of meaningful business examples the gap between Digitalization in dreams and in practice. The discussion scope was digital, omnichannel commerce. Business priorities drive IT solutions – Jani selected relevant and topical drivers to illustrate how Bilot’s full-stack commerce framework provides a state-of-the-art solution. He showed four use cases which have direct business benefit: contextual merchandizing, fast routine orders and searchandizing, live scheduling and synchronized logistics and margin management. All four use cases have a strong impact on topline revenue and operating income.

“Digital Commerce Success is more than just fancy webshops” – Jani Puroranta

Harnessing data and understanding customer behavior is the first step in building a world-class commerce solution. Bilot’s full-stack commerce is of course just one example of how companies can amplify and secure their competitiveness. It nevertheless closed the loop to Ala-Pietilä’s rhetoric and hooked into Keskinen’s narrative on UPM IT Triathlon, which is all about transforming, building and running.

The three discussions confirmed my hypothesis of how the IT market is evolving. As a contradiction to the widely spread simplification theme, in fact the IT game (and business technology landscape) is becoming more complex. Perhaps a better term is ‘more sophisticated’ because control has also improved. Enterprise solution landscapes are not entirely cloudified yet and the emergence of increasingly compelling and even disruptive software solutions beckons insightful decision-making on architecture and eco-systems.

For a while it looked like platform dominance (the classical definition that is) was a genuinely possible scenario. But innovation, competition and technological progress has kept the game very dynamic. Also the outsourcing (and off-shoring) trend is reaching maturity and there is evidence of on-shoring. Especially in the large enterprise category, companies’ IT partner/vendor strategy is undergoing a renaissance towards a more conscious segmentation of vendors into two or three categories.

In addition to an undisputed need for scalable global (RUN) solutions for AMS and infrastructure, the need for application development (TRANSFORM) and early adoption (BUILD) partners has re-surfaced.

IT vendors must be able to adapt to a multi-vendor environment where the joint-mission is to provide long-term customer value. This heterogeneous partner lay-out is the new platform – which means platform equals ecosystem.