يعمل WhatsApp Flows على تحسين وتبسيط كيفية قيام نشاطك التجاري بجمع بيانات العملاء. يمكن لمؤسستك بسهولة الحصول على معلومات منظمة من التفاعلات مع العملاء، الذين بدورهم يستمتعون بتجربة مستخدم إيجابية على واتساب. يعمل WhatsApp Flows بشكل جيد لتجميع بيانات العملاء المحتملين، وإجراء استطلاعات رأي، ومساعدة العملاء على حجز المواعيد، وإرسال أسئلة العملاء واستفساراتهم، وغير ذلك الكثير.
أفضل ما في هذا الأمر أنه يمكنك تقديم كل هذه الخيارات لعملائك دون الحاجة إلى تطوير تطبيق وبرامج معقدة: ببساطة، استخدِم واتساب كواجهة أمامية واستعِن بـ webhook لتسجيل الردود كرسائل JSON ومعالجة المعلومات واسترداد البيانات التي تحتاج إليها.
باستخدام شركة وهمية كمثال، يوضح العرض التوضيحي هذا إعداد استطلاع رأي العملاء على واتساب باستخدام Webhooks. سيجمع استطلاع الرأي الملاحظات ككيفية اكتشاف العميل للشركة وأنواع الجولات المفضلة لديه؛ حتى تتمكن الشركة من تقديم خدمة أفضل للعملاء الحاليين والمستقبليين.
للمتابعة، تأكَّد من وجود ما يلي:
إذا كنتَ ترغب في معاينة المشروع، فيمكنك الاطِّلاع على الرمز البرمجي الكامل.
هناك طريقتان لإنشاء دفق: استخدام واجهة مستخدم أداة إنشاء عمليات الدفق أو واجهة Flows API. يستخدم العرض التوضيحي هذا واجهة Flows API لإعداد استطلاع الرأي برمجيًا.
لإنشاء دفق يستخدم البيانات الديناميكية من الخادم الخاص بك، يمكنك إنشاء نقطة نهاية من شأنها ربط استطلاع الرأي بالخادم الخاص بك. باستخدام نقطة النهاية، يمكنك التحكم في منطق التنقل بين شاشات الدفق، أو تعبئة بيانات الدفق من الخادم الخاص بك، أو إظهار/إخفاء المكونات على الشاشة استنادًا إلى تفاعل المستخدم.
لا يستخدم مثال دفق استطلاع الرأي الذي سيتم مناقشته أي نقطة نهاية لعدم وجود تبادل ديناميكي للبيانات بينه وبين الخادم. ستستخدم دردشة webhook لتسجيل المعلومات الواردة من استطلاع الرأي. بالإضافة إلى ذلك، يمكنك إرفاق عمليات الدفق بقالب رسالة في مدير واتساب.
أولاً، قم بإنشاء تطبيق Flask للتفاعل مع واجهة Flows API. قم بتشغيل الأمر التالي في الوحدة الطرفية لإنشاء بيئة افتراضية.
python -m venv venv
ثم استخدِم الأمر أدناه لتنشيط البيئة.
source venv/bin/activate
بعد ذلك، استخدِم الأمر التالي لتثبيت الحزم المطلوبة.
pip install requests flask python-dotenv
ستستخدم Flask لإنشاء المسارات والتفاعل مع واجهة Flows API، وطلبات إرسال طلبات HTTP، وpython-dotenv لتحميل متغيرات البيئة.
قم الآن بإنشاء ملف بيئة يُسمى .env وألصقه في المعلومات التالية.
VERIFY_TOKEN = ACCESS_TOKEN = WHATSAPP_BUSINESS_ACCOUNT_ID = PHONE_NUMBER_ID =
قم بتعيين القيم استنادًا إلى معلومات حساب المطور الخاص بك. يمكنك استخدام أي سلسلة من أجل VERIFY_TOKEN
. المتغيران WHATSAPP_BUSINESS_ACCOUNT_ID
وPHONE_NUMBER_ID
هما المعرِّفات الفريدة لحسابك والتي يتم إنشاؤها تلقائيًا بواسطة Meta. The ACCESS_TOKEN
مخصص للمصادقة والتصريح لطلبات واجهة API.
للوصول إلى هذه المعلومات من لوحة التحكم في تطبيق Meta الخاص بك، انقر على واتساب > إعداد واجهة API في لوحة التنقل على الجانب الأيمن كما هو موضح في لقطة الشاشة أدناه.
أخيرًا، أنشِئ في نفس الدليل ملفًا بالاسم main.py يحتوي على منطق Python من أجل إنشاء عمليات الدفق وwebhook.
لإنشاء دفق، قم أولاً بإضافة الحزم التالية إلى main.py
.
import os import uuid import requests from dotenv import load_dotenv from flask import Flask, request, make_response, json
بعد ذلك، قم بإضافة جزء الرمز البرمجي التالي إلى main.py
لتشغيل المتغيرات. يقوم الجزء أيضًا بتشغيل Flask واستدعاء طريقة load_dotenv()
للمساعدة على تحميل المتغيرات.
app = Flask(__name__) load_dotenv() PHONE_NUMBER_ID = os.getenv('PHONE_NUMBER_ID') VERIFY_TOKEN = os.getenv('VERIFY_TOKEN') ACCESS_TOKEN = os.getenv('ACCESS_TOKEN') WHATSAPP_BUSINESS_ACCOUNT_ID = os.getenv('WHATSAPP_BUSINESS_ACCOUNT_ID') created_flow_id = "" messaging_url = f"https://graph.facebook.com/v18.0/{PHONE_NUMBER_ID}/messages" auth_header = {"Authorization": f"Bearer {ACCESS_TOKEN}"} messaging_headers = { "Content-Type": "application/json", "Authorization": f"Bearer {ACCESS_TOKEN}", }
ثم أضِف المسار التالي لمعالجة إنشاء الدفق.
@app.route("/create-flow", methods=["POST"]) def create_flow(): flow_base_url = ( f"https://graph.facebook.com/v18.0/{WHATSAPP_BUSINESS_ACCOUNT_ID}/flows" ) flow_creation_payload = {"name": "<FLOW-NAME>", "categories": '["SURVEY"]'} flow_create_response = requests.request( "POST", flow_base_url, headers=auth_header, data=flow_creation_payload ) try: global created_flow_id created_flow_id = flow_create_response.json()["id"] graph_assets_url = f"https://graph.facebook.com/v18.0/{created_flow_id}/assets" upload_flow_json(graph_assets_url) publish_flow(created_flow_id) print("FLOW CREATED!") return make_response("FLOW CREATED", 200) except: return make_response("ERROR", 500)
تستدعي الوظيفة نقطة نهاية عمليات الدفق (flow_base_url)
خلال مرور حمولة البيانات (flow_creation_payload)
التي تحتوي على الاسم وفئة الدفق. القيم المحتملة للفئة هي: SIGN_UP
أو SIGN_IN
أو APPOINTMENT_BOOKING
أو LEAD_GENERATION
أو CONTACT_US
أو CUSTOMER_SUPPORT
أو SURVEY
أو OTHER
.
استبدِل <FLOW-NAME>
بالاسم الذي تريده — على سبيل المثال، survey_flow.
بعد أن يقوم الرمز البرمجي بإنشاء الدفق، يستخرج created_flow_id
لتحميل نص JSON الخاص به.
أنشِي ملف survey.json
باستخدام عناصر المحتوى هذا. يحتوي JSON على هيكل الدفق.
ثم قم بلصق الرمز البرمجي التالي في ملف main.py
.
def upload_flow_json(graph_assets_url): flow_asset_payload = {"name": "flow.json", "asset_type": "FLOW_JSON"} files = [("file", ("survey.json", open("survey.json", "rb"), "application/json"))] res = requests.request( "POST", graph_assets_url, headers=auth_header, data=flow_asset_payload, files=files, ) print(res.json())
تقوم هذه الوظيفة بتحميل بيانات JSON من survey.json
إلى نقطة نهاية أصول الدفق.
في جزء الرمز البرمجي أدناه، عندما يقوم المستخدم بتشغيل إجراء النقر، فإنه بذلك يقوم بتشغيل on-click-action
، ويسجل البيانات ضمن حمولة البيانات. يُشير الحقل "name": "complete"
إلى اكتمال الدفق. سيتم إغلاقه وسيتم إرسال حمولة البيانات إلى خادم webhook الخاص بك.
... "on-click-action": { "name": "complete", "payload": { "source": "${form.source}", "tour_type": "${form.tour_type}", "tour_quality": "${form.tour_quality}", "decision_influencer": "${form.decision_influencer}", "tour_guides": "${form.tour_guides}", "aspects_enjoyed": "${form.aspects_enjoyed}", "improvements": "${form.improvements}", "recommend": "${form.recommend}", "return_booking": "${form.return_booking}" } } ...
قد تتوافق القيم الموجودة داخل كائنات بيانات الحمولة مع مكونات الدفق (تشبه أسماء العناصر في نماذج HTML) أو كائنات البيانات. تُسمى المفاتيح المرتبطة بقيم حمولة البيانات هذه أسماء، على غرار كيفية تعيين المتغيرات في لغات البرمجة.
تحتوي عناصر data-source
أيضًا على معرفات تعمل كمفاتيح للقيم. يرسل الرمز البرمجي هذا المعرفات للاختيارات. على سبيل المثال، إذا اختار المستخدم Likely
من أجل data-source
أدناه، فسيتم إرسال الرمز البرمجي1
. بمجرد استلام البيانات، يمكنك مطابقة مصادر البيانات.
... { "type": "RadioButtonsGroup", "required": true, "name": "return_booking", "data-source": [ { "id": "0", "title": "Very likely" }, { "id": "1", "title": "Likely" }, { "id": "2", "title": "Undecided" }, { "id": "3", "title": "Unlikely" }, { "id": "4", "title": "Very likely" } ] } ...
يتضمن الدفق شاشة واحدة تحتوي على تسعة أسئلة متعددة الخيارات، كما هو موضح أدناه.
يمكنك استكشاف تفاصيل عناصر JSON في وثائق المطور.
بعد ذلك، ألصق الوظيفة أدناه في ملف main.py
لإضافة المنطق لنشر الدفق. الدفق المنشور جاهز للطرح، لذا لن تتمكن من إجراء المزيد من التغييرات.
def publish_flow(flow_id): flow_publish_url = f"https://graph.facebook.com/v18.0/{flow_id}/publish" requests.request("POST", flow_publish_url, headers=auth_header)
تستدعي الوظيفة نقطة نهاية النشر أثناء المرور بمعرِّف الدفق.
ألصق الوظيفة التالية في ملف main.py
لإرسال الدفق إلى مستخدم واتساب. تستدعي الوظيفة نقطة نهاية رسائل واجهة API السحابة أثناء تمرير حمولة بيانات الدفق.
def send_flow(flow_id, recipient_phone_number): # Generate a random UUID for the flow token flow_token = str(uuid.uuid4()) flow_payload = json.dumps( { "type": "flow", "header": {"type": "text", "text": "Survey"}, "body": { "text": "Your insights are invaluable to us – please take a moment to share your feedback in our survey." }, "footer": {"text": "Click the button below to proceed"}, "action": { "name": "flow", "parameters": { "flow_message_version": "3", "flow_token": flow_token, "flow_id": flow_id, "flow_cta": "Proceed", "flow_action": "navigate", "flow_action_payload": {"screen": "SURVEY_SCREEN"}, }, }, } ) payload = json.dumps( { "messaging_product": "whatsapp", "recipient_type": "individual", "to": str(recipient_phone_number), "type": "interactive", "interactive": json.loads(flow_payload), } ) requests.request("POST", messaging_url, headers=messaging_headers, data=payload) print("MESSAGE SENT")
تحتوي حمولة بيانات الدفق على تفاصيل الدفق. يُتيح لك حقل action.parameters.flow_token
تمرير معرِّف فريد لرسالة الدفق التي سيتم إرسالها من العميل إلى webhook الخاص بك بمجرد اكتمال الدفق. في هذا العرض التوضيحي، ستستخدم معرفًا عشوائيًا (uuid). يقوم الرمز البرمجي بتعيين action.parameters.flow_action_payload.screen
مثل SURVEY_SCREEN
وهو معرِّف الشاشة الذي تريد عرضه عند قيام المستخدم بالنقر action.parameters.flow_cta
.
يُعَد منطق webhook واضح ومباشر. ويحتوي هذا المنطق على وظيفتين، webhook_get
وwebhook_post
لمعالجة طلبات GET
وPOST
بالترتيب. يستخدم الرمز البرمجي طلب GET
عند إضافة webhook إلى تطبيق Meta. ويقوم بإرجاع طلب hub.challenge
عند نجاحه. يقوم طلب POST
بطباعة حمولة بيانات الرسالة في الوحدة الطرفية.
@app.route("/webhook", methods=["GET"]) def webhook_get(): if ( request.args.get("hub.mode") == "subscribe" and request.args.get("hub.verify_token") == VERIFY_TOKEN ): return make_response(request.args.get("hub.challenge"), 200) else: return make_response("Success", 403)
يقوم طلب POST
باستخراج حمولة بيانات الرسالة ومعالجتها. ولأن الرمز البرمجي يناسب فقط حمولة بيانات الرسالة، فإنه بذلك يتناول الأخطاء عند تسجيل أي حمولة بيانات أخرى. لهذا السبب، يمكنك استخدام if
للتحقق من وجود نص messages
. بعد التحقق من وجود نص JSON messages
، يتم التحقق مرة أخرى لاستخراج رقم هاتف المرسل فقط في حالة وجود نص text
في حمولة البيانات messages
.
@app.route("/webhook", methods=["POST"]) def webhook_post(): # checking if there is a messages body in the payload if ( json.loads(request.get_data())["entry"][0]["changes"][0]["value"].get( "messages" ) ) is not None: """ checking if there is a text body in the messages payload so that the sender's phone number can be extracted from the message """ if ( json.loads(request.get_data())["entry"][0]["changes"][0]["value"][ "messages" ][0].get("text") ) is not None: user_phone_number = json.loads(request.get_data())["entry"][0]["changes"][ 0 ]["value"]["contacts"][0]["wa_id"] send_flow(created_flow_id, user_phone_number) else: flow_reply_processor(request) return make_response("PROCESSED", 200)
بالإضافة إلى ذلك، يتعين عليك استخدام وظيفة أداة المساعدة التالية التي تُسمى flow_reply_processor
لاستخراج الرد من الدفق وإرساله مرة أخرى إلى المستخدم. ولأن رد الدفق يحتوي على معرِّف الخيار المحدد عند تسجيل البيانات الواردة من RadioButtonsGroups
، فإن الوظيفة تطابق المعرفات مع قيم السلسلة المقابلة.
def flow_reply_processor(request): flow_response = json.loads(request.get_data())["entry"][0]["changes"][0]["value"][ "messages" ][0]["interactive"]["nfm_reply"]["response_json"] flow_data = json.loads(flow_response) source_id = flow_data["source"] tour_type_id = flow_data["tour_type"] tour_quality_id = flow_data["tour_quality"] decision_influencer_id = flow_data["decision_influencer"] tour_guides_id = flow_data["tour_guides"] aspects_enjoyed_id = flow_data["aspects_enjoyed"] improvements_id = flow_data["improvements"] recommend_id = flow_data["recommend"] return_booking_id = flow_data["return_booking"] match source_id: case "0": source = "Online search" case "1": source = "Social media" case "2": source = "Referral from a friend/family" case "3": source = "Advertisement" case "4": source = "Others" match tour_type_id: case "0": tour_type = "Cultural tour" case "1": tour_type = "Adventure tour" case "2": tour_type = "Historical tour" case "3": tour_type = "Wildlife tour" match tour_quality_id: case "0": tour_quality = "1 - Poor" case "1": tour_quality = "2 - Below Average" case "2": tour_quality = "3 - Average" case "3": tour_quality = "4 - Good" case "4": tour_quality = "5 - Excellent" match decision_influencer_id: case "0": decision_influencer = "Positive reviews" case "1": decision_influencer = "Pricing" case "2": decision_influencer = "Tour destinations offered" case "3": decision_influencer = "Reputation" match tour_guides_id: case "0": tour_guides = "Knowledgeable and friendly" case "1": tour_guides = "Knowledgeable but not friendly" case "2": tour_guides = "Friendly but not knowledgeable" case "3": tour_guides = "Neither of the two" case "4": tour_guides = "I didn’t interact with them" match aspects_enjoyed_id: case "0": aspects_enjoyed = "Tourist attractions visited" case "1": aspects_enjoyed = "Tour guide's commentary" case "2": aspects_enjoyed = "Group dynamics/interaction" case "3": aspects_enjoyed = "Activities offered" match improvements_id: case "0": improvements = "Tour itinerary" case "1": improvements = "Communication before the tour" case "2": improvements = "Transportation arrangements" case "3": improvements = "Advertisement" case "4": improvements = "Accommodation quality" match recommend_id: case "0": recommend = "Yes, definitely" case "1": recommend = "Yes, but with reservations" case "2": recommend = "No, I would not" match return_booking_id: case "0": return_booking = "Very likely" case "1": return_booking = "Likely" case "2": return_booking = "Undecided" case "3": return_booking = "Unlikely" reply = ( f"Thanks for taking the survey! Your response has been recorded. This is what we received:\n\n" f"*How did you hear about our tour company?*\n{source}\n\n" f"*Which type of tour did you recently experience with us?*\n{tour_type}\n\n" f"*On a scale of 1 to 5, how would you rate the overall quality of the tour?*\n{tour_quality}\n\n" f"*What influenced your decision to choose our tour company?*\n{decision_influencer}\n\n" f"*How knowledgeable and friendly were our tour guides?*\n{tour_guides}\n\n" f"*What aspects of the tour did you find most enjoyable?*\n{aspects_enjoyed}\n\n" f"*Were there any aspects of the tour that could be improved?*\n{improvements}\n\n" f"*Would you recommend our tour company to a friend or family member?*\n{recommend}\n\n" f"*How likely are you to book another tour with us in the future?*\n{return_booking}" ) user_phone_number = json.loads(request.get_data())["entry"][0]["changes"][0][ "value" ]["contacts"][0]["wa_id"] send_message(reply, user_phone_number) After the extraction, the following send_message function sends the responses to the sender. def send_message(message, phone_number): payload = json.dumps( { "messaging_product": "whatsapp", "to": str(phone_number), "type": "text", "text": {"preview_url": False, "body": message}, } ) requests.request("POST", messaging_url, headers=messaging_headers, data=payload) print("MESSAGE SENT")
ترسل الوظيفة الرد باستخدام نقطة نهاية الرسالة النصية لواجهة API السحابة.
يجب أن يكون التطبيق قيد التشغيل قبل تكوين webhook في وحدة تحكم Meta للمطوّرين. ولذلك، استخدِم الأمر flask --app main run --port 5000
في الوحدة الطرفية لتشغيل الرمز البرمجي. سترى رسالة * Running on http://127.0.0.1:5000
في الوحدة الطرفية إذا تم إعداد كل شيء بشكل صحيح.
بعد ذلك، قم بتشغيل الأمر ngrok
http 5000
في الوحدة الطرفية للحصول على عنوان URL الذي يرتبط بتطبيقك. انسخ هذا الرابط.
في وحدة تحكم Meta للمطوّرين، ضمن واتساب في لوحة التنقل على الجانب الأيمن، انقر على تكوين.
في بطاقة Webhook، انقر على تعديل. بعد ذلك، في مربع الحوار الموجود في حقل عنوان URL للاستدعاء، أضِف عنوان URL الذي تم نسخه وقم بإرفاق /webhook
. في حقل التحقق من الرمز، أضِف الرمز من المتغير .env
الخاص بالملف TOKEN
.
بمجرد الانتهاء، انقر على تحقق وحفظ. وسيتم إغلاق مربع الحوار. انقر على إدارة وقم بتحديد حقل الرسائل. يجب أن تظهر المعلومات بصورة مشابهة للصورة أدناه، مع عنوان URL للاستدعاء والمعلومات التي تم إخفاؤها ضمن التحقق من الرمز والرسائل المدرجة ضمن حقول Webhook.
أصبح webhook جاهز الآن.
في مثيل الوحدة الطرفية الجديدة، قم بتشغيل أمر cURL أدناه لإنشاء دفق.
curl --location --request POST 'http://127.0.0.1:5000/create-flow'
في مثيل الوحدة الطرفية الذي يعرض نتائج webhook الخاص بك، سترى رسالة مشابهة لتلك الموضحة أدناه.
عندما يرسل مستخدم ما رسالة إلى رقم واتساب الخاص بك، فإنه بذلك يتلقى الدفق كرد، كما في لقطة الشاشة أدناه.
يتلقى ردًا بإجاباتهم بعد إكمال استطلاع الرأي.
أي رسالة يرسلها المستخدم إلى رقمك تؤدي إلى تشغيل الدفق. بالنسبة إلى حالة الاستخدام الخاصة بك، قم بتخصيص الرمز البرمجي الخاص بك لإرسال دفق استطلاع الرأي فقط في حالات معينة، على سبيل المثال، بعد قيام المستخدم بإجراء دردشة مع نشاطك التجاري.
يعمل WhatsApp Flows على تحسين تجربة المستخدم من خلال واجهات تفاعلية لجمع البيانات المنظمة، مثل الردود على استطلاع الرأي لشركة سياحية افتراضية. يقوم النشاط التجاري فقط بإنشاء تطبيق Flask، وتنفيذ الرمز البرمجي للغة Python لإنشاء عمليات الدفق ونشرها عبر واجهة WhatsApp Flows API، وإعداد webhook للاستماع إلى الرسائل الواردة، وتشغيل التطبيق لتمكين مجموعة الردود على استطلاع الرأي.
يُتيح WhatsApp Flows لمؤسستك تجميع البيانات بصورة سهلة وبسيطة؛ حيث يمكن أن يساعد على تحسين معدلات إكمال تفاعلات العملاء. استخدِم عملية مشابهة لإعداد استطلاعات الرأي الخاصة بك وتقديم دعم العملاء ومساعدتهم على حجز المواعيد وغير ذلك الكثير.
تابِع استكشاف إمكانات WhatsApp Flows. جرِّبه الآن.