SalesforceのVisualforceページを外部に公開したい場合はForce.comサイトを仕組みを使用します。ページ全体をForce.comサイトで開発できるときは話が簡単ですが、既存のWebサイト内にある入力フォームだけをForce.comサイトで構築したい場合は少し検討が必要な部分があるので今回その部分について確認してみました。
はじめに
Salesforceと関係無いWebサイトにForce.comサイトページを表示するにはiframeで表示させます。ですが、ただiframeで表示するだけだとモバイル端末でアクセスした際にレイアウトが崩れてしまいます。
社外の様々な人たちがアクセスする外部サイトの場合は画面サイズに合わせてレイアウトが調整されるレスポンシブ対応を考慮する必要があります。
※iframeのレスポンシブ対応についてはこちらのサイトがとても参考になりました。
iframeのレスポンシブ対応はもの凄く簡単 | ウェブデザインスクールをお探しならWEB塾 超現場主義|東京(上野)・長野・浜松・札幌
iframeのレスポンシブ対応についての動作検証
まずは通常のWebサイトだけでiframeのレスポンシブ対応がうまくいくかを確認してみます。Webサイトの立ち上げはHerokuとLightning Design SystemのGetting Startedの手順で用意しました。
Step 1: Initialize your project
ディレクトリ作成
$ mkdir demo_slds_heroku $ cd demo_slds_heroku
初期設定
$ npm init
npm initで入力する内容
name:
version:
description:
entry point: (index.js) [server.js]
test command:
git repository:
keywords:
author:
license: (ISC)
package.jsonの内容
{ "name": "demo_slds_heroku", "version": "0.0.0", "description": "demo_slds_heroku", "main": "server.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC" }
Step 2: Install node dependencies - Express
$ npm install express --save
Step 3: Create public/index.html
$ mkdir public $ touch public/index.html
index.htmlの内容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="x-ua-compatible" content="ie=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Playground</title> </head> <body> Kaixo! </body> </html>
Step 4: Create server.js
$ touch server.js
server.jsの内容
var express = require('express'); var app = express(); var port = process.env.PORT || 8080; // Serve static files app.use(express.static(__dirname + '/public')); // Serve your app console.log('Served: http://localhost:' + port); app.listen(port);
localhostの起動
$ node server.js
ここでGoogleマップを埋め込んでみます。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="x-ua-compatible" content="ie=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Playground</title> </head> <body> <div> <iframe src="略" width="600" height="450" frameborder="0" style="border:0" allowfullscreen></iframe> </div> </body> </html>
この時点ではiframeの幅や高さが固定のためブラウザの幅小さくなると表示されない領域が発生することを確認できます。
続いて最初に記載したリンク先の手順どおりにcssを適用させます。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="x-ua-compatible" content="ie=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <title>Playground</title> <style> .google_map{ position:relative; width:100%; height:0; padding-top:75%; } .google_map iframe{ position:absolute; top:0; left:0; width:100%; height:100%; } </style> </head> <body> <div class="google_map"> <iframe src="略" width="600" height="450" frameborder="0" style="border:0" allowfullscreen></iframe> </div> </body> </html>
無事にiframeの内容がページ幅に合わせて動的に切り替わることを確認できました。
目的の動作検証を行うことができましたが、Lightning Design Systemを適用してHerokuへデプロイまでやっておきます。
Step 5: Download the Salesforce Lightning Design System
Step 6: Add components
styleタグの中身を別のcssファイルに移動したり、ヘッダーをつけてこんな感じ。
index.htmlの中身
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="x-ua-compatible" content="ie=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" type="text/css" href="/assets/styles/salesforce-lightning-design-system.css" /> <link rel="stylesheet" type="text/css" href="/css/style.css" /> <title>Playground</title> </head> <body> <div class="slds-grid slds-wrap"> <!-- Header --> <nav class="slds-col slds-size_1-of-1"> <div class="slds-page-header"> <div class="slds-page-header__row"> <div class="slds-page-header__col-title"> <div class="slds-media"> <div class="slds-media__figure"> <span class="slds-icon_container slds-icon-standard-opportunity" title="opportunity"> <svg class="slds-icon slds-page-header__icon" aria-hidden="true"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/assets/icons/standard-sprite/svg/symbols.svg#opportunity" /> </svg> <span class="slds-assistive-text">Heroku Demo</span> </span> </div> <div class="slds-media__body"> <div class="slds-page-header__name"> <div class="slds-page-header__name-title"> <h1> <span class="slds-page-header__title slds-truncate" title="Rohde Corp - 80,000 Widgets">Heroku Demo</span> </h1> </div> </div> <p class="slds-page-header__name-meta">T.Yoshikawa Labs</p> </div> </div> </div> </div> </div> </nav> <!-- Main --> <main class="slds-col slds-size_1-of-1 slds-p-around_small"> <div class="slds-section"> <h3 class="slds-section__title slds-theme_shade slds-m-bottom_small"> <span class="slds-truncate slds-p-horizontal_small" title="Section Title">Google Map</span> </h3> <!-- Google Map --> <div class="google_map"> <iframe src="略" width="600" height="450" frameborder="0" style="border:0" allowfullscreen></iframe> </div> </div> </main> </div> </body> </html>
こうなります。
Step 7: Deploy to Heroku
$ touch Procfile
Procfileの内容
web: node server.js
Herokuにログイン
$ heroku login Email: [your@email.com] Password: [typing will be hidden] $ git init $ heroku create [name-of-your-project] $ git add . $ git commit -m "Initial commit" $ git push heroku master $ heroku open
こんな感じでHerokuにデプロイしてページを表示できるようにしました。
WebサイトへのSalesforceサイトの組み込み
それではSalesforceサイトの組み込みを試してみます。はじめに外部に公開するためサイト設定でドメインを指定します。
埋め込むためのVisualforceページを用意します。
サイト設定でVisualforceページを表示できるように設定します。これでSalesforceにログインしなくてもアクセスできるVisualforceページを用意できました。
※iframeに別ドメインのサイトを埋め込むことになるのでクリックジャック保護レベルの設定で許可が必要になると思います。
あとは動作確認できるように入力フォームを実装します。
簡易的につくっていますがコードはこんな感じ。
<apex:page showHeader="false" sidebar="false"> <head> <apex:slds /> </head> <body> <div xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="vf-page"> <div class="slds-p-around_small"> <!-- Field 01 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-01">Form Label 01</label> <div class="slds-form-element__control"> <input type="text" id="form-element-01" class="slds-input" /> </div> </div> <!-- Field 02 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-02">Form Label 02</label> <div class="slds-form-element__control"> <input type="text" id="form-element-02" class="slds-input" /> </div> </div> <!-- Field 03 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-03">Form Label 03</label> <div class="slds-form-element__control"> <input type="text" id="form-element-03" class="slds-input" /> </div> </div> <!-- Field 04 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-04">Form Label 04</label> <div class="slds-form-element__control"> <input type="text" id="form-element-04" class="slds-input" /> </div> </div> <!-- Field 05 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-05">Form Label 05</label> <div class="slds-form-element__control"> <input type="text" id="form-element-05" class="slds-input" /> </div> </div> <!-- Field 06 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-06">Form Label 06</label> <div class="slds-form-element__control"> <input type="text" id="form-element-06" class="slds-input" /> </div> </div> <!-- Field 07 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-07">Form Label 07</label> <div class="slds-form-element__control"> <input type="text" id="form-element-07" class="slds-input" /> </div> </div> <!-- Field 08 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-08">Form Label 08</label> <div class="slds-form-element__control"> <input type="text" id="form-element-08" class="slds-input" /> </div> </div> <!-- Field 09 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-09">Form Label 09</label> <div class="slds-form-element__control"> <input type="text" id="form-element-09" class="slds-input" /> </div> </div> <!-- Field 10 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-10">Form Label 10</label> <div class="slds-form-element__control"> <input type="text" id="form-element-10" class="slds-input" /> </div> </div> <!-- button --> <div class="slds-m-top_small"> <button class="slds-button slds-button_brand">問い合わせ</button> </div> </div> </div> </body> </apex:page>
Salesforceサイト側のページが用意できたのでHerokuで用意したWebサイトへiframeで組み込んでみます。まずはレスポンシブ対応無しバージョン。画面サイズに関わらず幅や高さが固定されてしまい正しく表示されません。
続いてレスポンシブ対応ありバージョンです。画面の幅に合わせてフォームが自然に表示されました。
幅を小さくしたときはこのように表示されます。
これでSalesforceサイトのページをWebサイトに埋め込むことができました。iframeによる表示となりますが、Salesforceでつくった入力フォームを自然な見た目で表示することができます。
実際のモバイル端末でアクセスして確認してみました。※iPhone
問題なさそうです。実際のプロジェクトではAndroid端末やIEなどのブラウザで問題ないかも確認してみ他方が良いと思います。(大丈夫だと思いますが)
iframeの高さ指定
サンプルでは%になっていますが、入力フォームなど横幅は変わっても高さを変えたくない場合は、px指定にすることで対応できます。
iframeとページ遷移
当然ですがiframe内でページ遷移するとiframeの中だけでページ遷移が行われます。
JS処理でのページ遷移の場合は下記のような感じにすると親フレームでページ遷移できるので忘れないようにします。
parent.location.href=<url>;
WebサイトへのForce.comサイトページの埋め込みはこんな感じで実現できました。
サンプルコード
最後に今回検証したときのサンプルコードです。
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8" /> <meta http-equiv="x-ua-compatible" content="ie=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <link rel="stylesheet" type="text/css" href="/assets/styles/salesforce-lightning-design-system.css" /> <link rel="stylesheet" type="text/css" href="/css/style.css" /> <title>Playground</title> </head> <body> <div class="slds-grid slds-wrap"> <!-- Header --> <nav class="slds-col slds-size_1-of-1"> <div class="slds-page-header"> <div class="slds-page-header__row"> <div class="slds-page-header__col-title"> <div class="slds-media"> <div class="slds-media__figure"> <span class="slds-icon_container slds-icon-standard-opportunity" title="opportunity"> <svg class="slds-icon slds-page-header__icon" aria-hidden="true"> <use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="/assets/icons/standard-sprite/svg/symbols.svg#opportunity" /> </svg> <span class="slds-assistive-text">Heroku Demo</span> </span> </div> <div class="slds-media__body"> <div class="slds-page-header__name"> <div class="slds-page-header__name-title"> <h1> <span class="slds-page-header__title slds-truncate" title="T.Yoshikawa Labs">Heroku Demo</span> </h1> </div> </div> <p class="slds-page-header__name-meta">T.Yoshikawa Labs</p> </div> </div> </div> </div> </div> </nav> <!-- Main --> <main class="slds-col slds-size_1-of-1 slds-p-around_small"> <!-- Salesforce Form --> <div class="slds-section"> <!-- Salesforce Form Header --> <h3 class="slds-section__title slds-theme_shade slds-m-bottom_small"> <span class="slds-truncate slds-p-horizontal_small" title="Section Title">Salesforce Form</span> </h3> <!-- Salesforce Form Main --> <div class="iframe-section"> <iframe src="<your salesforce page url>" width="600" height="600" frameborder="0" style="border:0" allowfullscreen></iframe> </div> </div> <!-- Google Map --> <div class="slds-section"> <!-- Google Map Header --> <h3 class="slds-section__title slds-theme_shade slds-m-bottom_small"> <span class="slds-truncate slds-p-horizontal_small" title="Section Title">Google Map</span> </h3> <!-- Google Map Main --> <div class="iframe-section"> <iframe src="<your google map url>" width="600" height="450" frameborder="0" style="border:0" allowfullscreen></iframe> </div> </div> </main> </div> </body> </html>
style.css
.iframe-section { position:relative; width:100%; height:0; padding-top:650px; } .iframe-section iframe { position:absolute; top:0; left:0; width:100%; height:100%; min-height: 600px; }
Salesforce Form Page
<apex:page showHeader="false" sidebar="false"> <head> <apex:slds /> <script type="text/javascript"> function move() { parent.location.href="<your salesforce thanks page url>"; } </script> </head> <body> <div xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="vf-page"> <div class="slds-p-around_small"> <!-- Field 01 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-01">Form Label 01</label> <div class="slds-form-element__control"> <input type="text" id="form-element-01" class="slds-input" /> </div> </div> <!-- Field 02 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-02">Form Label 02</label> <div class="slds-form-element__control"> <input type="text" id="form-element-02" class="slds-input" /> </div> </div> <!-- Field 03 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-03">Form Label 03</label> <div class="slds-form-element__control"> <input type="text" id="form-element-03" class="slds-input" /> </div> </div> <!-- Field 04 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-04">Form Label 04</label> <div class="slds-form-element__control"> <input type="text" id="form-element-04" class="slds-input" /> </div> </div> <!-- Field 05 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-05">Form Label 05</label> <div class="slds-form-element__control"> <input type="text" id="form-element-05" class="slds-input" /> </div> </div> <!-- Field 06 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-06">Form Label 06</label> <div class="slds-form-element__control"> <input type="text" id="form-element-06" class="slds-input" /> </div> </div> <!-- Field 07 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-07">Form Label 07</label> <div class="slds-form-element__control"> <input type="text" id="form-element-07" class="slds-input" /> </div> </div> <!-- Field 08 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-08">Form Label 08</label> <div class="slds-form-element__control"> <input type="text" id="form-element-08" class="slds-input" /> </div> </div> <!-- Field 09 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-09">Form Label 09</label> <div class="slds-form-element__control"> <input type="text" id="form-element-09" class="slds-input" /> </div> </div> <!-- Field 10 --> <div class="slds-form-element"> <label class="slds-form-element__label" for="form-element-10">Form Label 10</label> <div class="slds-form-element__control"> <input type="text" id="form-element-10" class="slds-input" /> </div> </div> <!-- button --> <div class="slds-m-top_small"> <button class="slds-button slds-button_brand" onclick="move()">問い合わせ</button> </div> </div> </div> </body> </apex:page>
Salesforce Form Thanks Page
<apex:page showHeader="false" sidebar="false"> <head> <apex:slds /> <style> * { background-color: #255E9E; font-size: 20px; color: #fff; } </style> </head> <body> <div xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" id="vf-page"> <div class="slds-p-around_small"> Thanks! </div> </div> </body> </apex:page>