Tech & Design LAB

Zapier アプリを作って連携ソリューションを増やす話

#Zapier
author icon
Posted on
tech

こんにちは、HiCustomerの導入や活用について技術面での支援を担当しているカスタマーサクセスエンジニアの白坂です。先日HiCustomerのZapierアプリをリリースしましたのでその経緯をご紹介します。

背景

HiCustomerはSaaSを提供する企業に向けたカスタマーサクセスマネジメントツールです。SaaSの顧客データを元に、その顧客がSaaSから価値を引き出せているかを表すヘルススコアの可視化やそれを改善するためのアクションを促すなどを行うことができます。

そのため、顧客のプロダクト利用状況に加え、契約内容や問い合わせ、アンケート結果などの顧客データをHiCustomerに集約できることが求められます。一方でこれらのデータは様々なWebサービスやシステムにまたがって管理されており集約するために開発コストがかさんでしまうなどの課題が生じていました。

そこで、この課題を解決するために開発をせずとも顧客データを連携するソリューションの一つとして白羽の矢が立ったのがZapierです。

Zapierとは

Zapierは1500を超えるオンライン上のサービス同士をプログラミング不要で連携させ、ワークフローを作ることができる業務自動化ツールです。 Zapierのアプリを作成することでこれらのサービスと連携させることができるようになり、例えば問い合わせ管理ツールに新しい問い合わせが登録されたらHiCustomerに問い合わせ内容を登録するということがプログラミング不要でできるようになります。

Zapier アプリの作成に至った3つの理由

HiCustomerではZapierアプリを作るにあたり以下の特徴が魅力でした。

  1. 多くのBtoB SaaSが対応
  2. データの中間処理が可能
  3. アプリの作成が簡単

1. 多くのBtoB SaaSが対応

Zapierは2020年3月29日現在、他のワークフローツールに比べてBtoB向けのWebサービスが多く対応しており、SFA/CRMではSalesforceやHubspot, Kintone、問い合わせ管理ツールではZendeskやIntercom、アンケートツールではSurvey Monkeyなど、HiCustomerで必要な顧客データを保持するWebサービスの多くが対応している点が魅力的でした。

またWebサービスが対応していない場合でも、ZapierからAPIを呼び出したりWebhookの送信先として設定することが可能です。そのためアプリを提供していない場合でも多くのWebサービスが(少しの手間はかかりますが)プログラミング不要で連携することができます。

2. データの中間処理が可能

サービス間の連携の際、それぞれの仕様の違いから日付のフォーマットや文字を変換する必要があるケースが少なくありません。そのような場合でもFormatterという機能でサービス間の大抵の仕様の差は埋めることが可能です。コードを書かせないという強い意志を感じます。

3. アプリの作成が簡単

ZapierのアプリはGUIでも作成可能ですが、Zapier CLIが用意されており最低限以下のステップでデプロイまで行うことができ、実装もJavaScriptで行うため慣れ親しんだツールを利用して開発することができました。

  1. zapier loginでzapierにログイン
  2. zapier init app-nameでzapierアプリのテンプレートを作成
  3. テンプレートの中身を実装
  4. zapier pushでデプロイ

Zapierアプリでは主に以下の4つの要素から構成されます。

HiCustomerでは「データを登録する」仕組みのみが必要であったため「Authentication」と「Creates」の2つの処理を記述するだけで実装することができました。

以下、それぞれAuthenticationとCreatesの処理のサンプルですが、とてもシンプルに書くことができますね。

Authentication

    // Authorizationヘッダーで認証を行う場合のサンプル
    const testAuth = (z, bundle) => {
        const options = {
            method: 'GET',
            headers: {
                'Authorization': bundle.authData.apiToken
            }
        };
        return z.request('https://api.example.com/auth_check',options)
            .then(response => {
                if (response.status === 403) {
                    throw new Error('The API Key is invalid');
                }
            });
    };
    
    module.exports = { 
        // 認証の種類(他にもSessionやOAuth2など指定可能)
        type: 'custom',
        // 認証が通っているかを検証するための関数
        test: testAuth,
        // 認証に必要なパラメーター
        fields: [
            {
                label: 'API Token',
                key: 'apiToken',
                type: 'string',
                required: true,
                helpText: 'Found on your settings page.'
            }
        ]
    };

Creates

    module.exports = {
        key: 'resource', // Createを一意に認識するキー
        noun: 'Resource', // リソース名
        // ワークフロー作成画面で表示される名称や説明
        display: {
            label: 'Add Resource',
            description: 'Add New Customer.',
            important: true
        },
        operation: {
            // 入力値
            inputFields: [
                {
                    key: 'id',
                    label: 'ID',
                    required: true,
                    type: 'string'
                },
                {
                    key: 'name',
                    label: 'Name',
                    required: false,
                    type: 'string'
                }
            ],
            // データ送信処理
            perform: (z, bundle) => {
                let body = {
                    id: bundle.inputData.id,
                    name: bundle.inputData.name
                };
                const options = {
                    url: 'https://api.example.com/resource',
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json',
                        'api-token': bundle.authData.apiToken
                    },
                    body: JSON.stringify(body)
                };
    
                return z.request(options)
                    .then(response => {
                        if (response.status !== 200) {
                            throw new Error(response.content);
                        }
                        return JSON.parse(response.content)
                    });
            }
        }
    };

リリースして終わりにならないために

Zapierのアプリをリリースしたものの本当にユーザーの役に立っているのか、利用状況をトラッキングして提供方法やアプリを改善していきたいものですね。Zapierアプリ経由で送信されたリクエストは(User-Agent: Zapier)というヘッダーが付与されて送信されるため、今後はリクエストログを分析することでアプリ改善を行っていきたいと考えています!

最後に

HiCustomerを一緒に作り上げていくエンジニアを募集しています! 少しでも興味をお持ちいただけた方、ぜひお気軽にオフィスに遊びにきてください。弊社のVP of Engineeringの@hizeny まで、もしくは Wantedly でのご連絡をお待ちしています!

author icon
カスタマーサクセスエンジニア

SaaSやツールを触るのが好き。業務では顧客からの技術課題の解決だけでなく、他社のツールと合わせた解決策の提案をすることも。海が好きで余暇はサーフィンへ。