Skip to content

Integration Guides

Last Updated: 2026-03-09 Covers: Tawk.to Live Chat, PayTabs Payment Gateway, GTM Cross-Domain Tracking, Daftra ERP Related: .claude/CLAUDE.md (project context), public/_headers (CSP), src/layouts/Layout.astro (script placement)


  1. Tawk.to Live Chat
  2. PayTabs Payment Gateway
  3. GTM Cross-Domain Tracking
  4. Daftra ERP Configuration

  1. Go to https://www.tawk.to/signup
  2. Register with the company email (info@urwhats.com or sales@urwave.com)
  3. Verify email address
  1. Property Name: urWhats
  2. Site URL: https://urwhats.com
  3. Default Language: English
  4. Secondary Language: Arabic
  5. Time Zone: Asia/Riyadh (UTC+3)
SettingValue
Theme Color#45b33d (primary green)
Widget Title (EN)Chat with us
Widget Title (AR)تحدث معنا
Position (LTR/EN)Bottom-right
Position (RTL/AR)Bottom-left

WhatsApp button overlap note: The site already has a WhatsApp floating button fixed at bottom-[30px] end-[30px] (see src/layouts/Layout.astro line 46-55). The Tawk.to widget defaults to bottom-right as well. Options to avoid overlap:

  • Option A (recommended): Configure Tawk.to widget offset to sit ~80px above the WhatsApp button. Use the Tawk.to Advanced settings → Widget Position → Custom bottom margin of 100px.
  • Option B: Move the WhatsApp button to the opposite side of the Tawk.to widget. This requires editing Layout.astro classes (end-[30px]start-[30px]), but breaks the established UX pattern.
  • Option C: Hide the WhatsApp floating button entirely and rely on Tawk.to with a WhatsApp channel connected. Tawk.to supports WhatsApp as a channel under Channels → WhatsApp.

For RTL (Arabic) pages, the end-[30px] class on the WhatsApp button resolves to bottom-left. Tawk.to’s bottom-left position for RTL means they will overlap on Arabic pages too. Apply the same offset strategy for both directions.

Configure under Triggers → Add Trigger → Site Visitor:

English greeting:

Hi! :wave: How can we help you today? We typically respond in minutes.

Arabic greeting:

:wave: كيف يمكننا مساعدتك اليوم؟ نرد عادة خلال دقائق.

Trigger conditions:

  • Time on page: 15 seconds (avoid interrupting users immediately)
  • Pages visited: >= 1
  • Don’t show if chat is already open
DayHours (AST / UTC+3)
Sunday - Thursday9:00 AM - 6:00 PM
Friday - SaturdayOffline

Enable Offline Form for outside business hours:

  • Collect: Name, Email, Message
  • Offline message (EN): “We’re currently offline. Leave a message and we’ll get back to you during business hours (Sun-Thu, 9AM-6PM AST).”
  • Offline message (AR): “نحن غير متصلين حالياً. اترك رسالة وسنعود إليك خلال ساعات العمل (الأحد-الخميس، 9 صباحاً - 6 مساءً بتوقيت السعودية).“
  1. Go to Administration → Team Members
  2. Add agents with appropriate roles:
    • Admin: Full access to settings, billing, and analytics
    • Agent: Can respond to chats, view visitor info, no settings access
  3. Each agent should download the mobile app:
  4. Enable push notifications for new chats on mobile

The current CSP in public/_headers (line 6) needs these additions:

DirectiveAdd
script-srchttps://embed.tawk.to
connect-srchttps://va.tawk.to wss://va.tawk.to
frame-srchttps://tawk.to
img-srcAlready covered by https: glob

Updated CSP script-src segment (add after https://connect.facebook.net):

https://embed.tawk.to

Updated CSP connect-src segment (add after https://connect.facebook.net):

https://va.tawk.to wss://va.tawk.to

Updated CSP frame-src segment (add after https://www.facebook.com):

https://tawk.to

Add the following script block in src/layouts/Layout.astro before the closing </body> tag, after the Footer component and before the existing <script> blocks (around line 58):

<!-- Tawk.to Live Chat -->
<script is:inline>
var Tawk_API=Tawk_API||{}, Tawk_LoadStart=new Date();
(function(){
var s1=document.createElement("script"),s0=document.getElementsByTagName("script")[0];
s1.async=true;
s1.src='https://embed.tawk.to/PROPERTY_ID/WIDGET_ID';
s1.charset='UTF-8';
s1.setAttribute('crossorigin','*');
s0.parentNode.insertBefore(s1,s0);
})();
</script>

Replace PROPERTY_ID and WIDGET_ID with the values from the Tawk.to dashboard (Administration → Channels → Chat Widget → Direct Chat Link). The URL format is https://embed.tawk.to/{propertyId}/{widgetId}.

Use is:inline because Astro would otherwise bundle and transform the script, breaking the Tawk.to loader pattern that relies on synchronous global variable initialization.

  • Widget appears on English pages (bottom-right, offset above WhatsApp button)
  • Widget appears on Arabic pages (bottom-left, offset above WhatsApp button)
  • Chat greeting fires after 15 seconds on page
  • Agent receives notification when visitor sends a message
  • Offline form appears outside business hours
  • Widget theme color matches site green (#45b33d)
  • Mobile: widget is usable, does not overlap with WhatsApp button
  • CSP: no console errors related to tawk.to resources being blocked

CriteriaPayTabsTapStripeHyperPay
Daftra native integrationYesYesNoNo
Mada (local debit) supportYesYesNoYes
Saudi entityYes (Riyadh HQ)Yes (Bahrain/KSA)No (US)Yes (Riyadh)
Recurring billing APIYesYesYesYes
Apple PayYesYesYesYes
STC PayYesNoNoYes
Monthly feeVaries by planNoneNoneVaries
Per-transaction fee~2.25% + 1 SAR~2.75%2.9% + 1 SAR~2.5%
Setup time3-5 business days2-3 business days1-2 weeks (KYC)3-5 business days

Decision: PayTabs is recommended because:

  1. Native Daftra integration (Settings → Payment Gateways → PayTabs) — no custom code needed
  2. Saudi-headquartered company, understands local compliance
  3. Supports all Saudi payment methods including Mada and STC Pay
  4. Recurring billing API for SaaS subscription model

Alternative: Tap (tap.company) is also Daftra-native and has no monthly fee. Consider Tap if monthly gateway fees are a concern during early growth. Tap lacks STC Pay support.

HyperPay is NOT supported by Daftra natively — would require custom webhook integration and is not recommended for this setup.

  1. Go to https://www.paytabs.com
  2. Click Merchant Signup → select Saudi Arabia
  3. Fill in business details:
    • Legal Entity Name: urWave Company
    • Trade Name: urWhats
    • Commercial Registration: 7052775355
    • VAT Number: 300075277550003
    • Business Type: Technology / SaaS
    • Website: https://urwhats.com

Prepare these before starting the application:

  • Commercial Registration certificate (CR: 7052775355) — from Ministry of Commerce (mc.gov.sa)
  • National ID (or Iqama) of authorized signatory
  • Saudi bank account details (IBAN, bank name, account holder)
  • Company letterhead (optional, may be requested for verification)
  • Website URL with active content (https://urwhats.com)

Approval typically takes 3-5 business days after document submission.

Once PayTabs merchant account is approved:

  1. Log into PayTabs Merchant Dashboard (merchant.paytabs.com)

  2. Navigate to Developers → Key Management

  3. Copy these three values:

    • Profile ID (numeric)
    • Server Key (starts with S...)
    • Client Key (starts with C...)
  4. Log into Daftra (app.daftra.com)

  5. Go to Settings → Payment Gateways

  6. Select PayTabs from the list

  7. Enter:

    • Profile ID
    • Server Key
    • Client Key
    • Currency: SAR
  8. Enable desired payment methods:

    • Mada (Saudi local debit — most customers will use this)
    • Visa
    • Mastercard
    • Apple Pay
    • STC Pay
  9. Save configuration

Before going live:

  1. In PayTabs dashboard, switch to Sandbox/Test Mode
  2. In Daftra, use the sandbox credentials (separate Profile ID / Server Key / Client Key)
  3. Create a test invoice in Daftra
  4. Pay using test card numbers:
    • Visa: 4111 1111 1111 1111, any future expiry, CVV 123
    • Mada: Use PayTabs sandbox Mada test numbers (check their docs)
  5. Verify:
    • Payment page loads correctly with SAR currency
    • Payment completes and Daftra marks invoice as paid
    • Customer receives payment confirmation email from Daftra
  6. Switch to Live Mode once testing is complete
MethodTypeTypical Usage
MadaLocal debit card~70% of Saudi online payments
Visa / MastercardInternational credit/debit~20% of payments
Apple PayMobile walletGrowing adoption
STC PayMobile walletPopular with STC subscribers

Fees vary by PayTabs plan. Approximate rates for Saudi merchants:

ComponentRate
Per transaction~2.25% + 1 SAR
Monthly feeVaries (0-500 SAR depending on plan)
Refund feeOriginal transaction fee is not returned
Chargeback fee75 SAR per chargeback
SettlementT+2 business days to Saudi bank account

Negotiate rates based on expected transaction volume. PayTabs offers custom pricing for SaaS businesses with recurring billing.

For monthly SaaS subscriptions, use the PayTabs Recurring Payments API:

  1. On first payment, tokenize the card via PayTabs hosted payment page
  2. Store the tran_ref (transaction reference) and token returned by PayTabs
  3. For subsequent months, call the PayTabs recurring API with the stored token
  4. Handle failures: retry logic, card expiry notifications, grace periods

Daftra’s recurring invoice feature handles the invoice side. The payment execution requires either:

  • Manual: Customer pays each invoice via the Daftra payment link (PayTabs hosted page)
  • Automated: Custom integration using PayTabs recurring API + Daftra webhook (see Section 4.5)

For initial launch, manual payment via Daftra invoice links is simpler and sufficient.


PropertyValue
GTM ContainerGTM-KBKH4G46
Marketing siteurwhats.com
App (registration)app.urwhats.com
Meta Pixel1367382874855915 (separate, not covered here)

Problem: Users click “Start Free Trial” on urwhats.com and land on app.urwhats.com/register. Without cross-domain tracking, this navigation creates a new session in Google Analytics, losing all attribution data (UTM parameters, landing page, referral source).

Solution: GTM cross-domain linker tag that passes the _gl parameter between domains, maintaining session continuity.

In GTM (tagmanager.google.com → Container GTM-KBKH4G46):

  1. Open your GA4 Configuration Tag (or create one if using gtag.js directly)
  2. Under Fields to Set, add:
Field NameValue
linker{"domains": ["urwhats.com", "app.urwhats.com"], "accept_incoming": true, "decorate_forms": true}

Alternatively, if using the GA4 Configuration tag type:

  1. Go to Tags → GA4 Configuration Tag
  2. Click Configure Tag Settings → More Settings → Cross Domain Measurement
  3. Add domains:
    • urwhats.com
    • app.urwhats.com
  4. Check Accept incoming linker parameters
  5. Check Decorate forms (for any forms that submit cross-domain)
  6. Trigger: All Pages
  7. Save

Define these events for tracking key user actions. The marketing site (urwhats.com) pushes events via GTM. The app (app.urwhats.com) must also push events to the same GTM container.

Fired when a user clicks a “Choose Plan” or “Start Free Trial” button on the pricing page.

dataLayer.push({
event: 'plan_selected',
plan_name: 'growth', // 'growth', 'business', or 'enterprise'
plan_id: 1, // numeric plan ID
plan_price: 349, // price in SAR
plan_currency: 'SAR' // 'SAR' or 'USD'
});

Implementation: Add onclick handlers to the pricing CTA buttons in src/components/DynamicPlans.astro.

Fired on app.urwhats.com after a user successfully completes registration. This is the primary conversion event.

dataLayer.push({
event: 'registration_complete',
plan_name: 'growth',
plan_id: 1,
method: 'email' // 'email', 'google', 'phone'
});

Implementation: Must be added to the app.urwhats.com codebase (separate repo). Coordinate with the app development team.

Fired when a user clicks the language switcher.

dataLayer.push({
event: 'language_switch',
from_language: 'en',
to_language: 'ar'
});

Implementation: Add to the language switcher click handler in src/components/Navigation.astro.

3.4 Step 3: Google Ads Conversion Tracking

Section titled “3.4 Step 3: Google Ads Conversion Tracking”
  1. In Google Ads (ads.google.com):

    • Go to Tools → Conversions → New Conversion Action
    • Choose Website
    • Name: “Registration Complete”
    • Category: Sign-up
    • Value: Set to plan price or estimated LTV (e.g., 349 SAR for Growth plan)
    • Count: One conversion per click
    • Click-through window: 30 days
    • View-through window: 1 day
  2. In GTM, create a new tag:

    • Tag type: Google Ads Conversion Tracking
    • Conversion ID: (from Google Ads)
    • Conversion Label: (from Google Ads)
    • Conversion Value: {{plan_price}} (create a Data Layer Variable for plan_price)
    • Currency Code: {{plan_currency}}
    • Trigger: Custom Event → registration_complete
  3. Create GTM Variables (Data Layer type) for:

    • plan_name → Variable name: DLV - plan_name
    • plan_id → Variable name: DLV - plan_id
    • plan_price → Variable name: DLV - plan_price
    • plan_currency → Variable name: DLV - plan_currency
  1. Open GTM → Preview (top right button)
  2. Enter URL: https://urwhats.com
  3. Navigate to the pricing page
  4. Click a “Choose Plan” button
  5. Verify in the Preview panel:
    • plan_selected event fires with correct data
    • GA4 Configuration tag fires on all pages
    • Cross-domain linker is active (check tag details)
  6. Follow the link to app.urwhats.com/register
  7. Check the URL contains the _gl parameter (e.g., ?planid=1&_gl=1*abc123*...)
  8. In the Preview panel for app.urwhats.com:
    • GA4 tag fires and recognizes the incoming linker parameter
    • Session is continuous (same Client ID as urwhats.com)

Common issues:

  • _gl parameter not appearing: Check that the link uses a standard <a> tag (not JavaScript navigation). Ensure decorate_forms is enabled.
  • Session breaks: Verify both domains are listed in GA4 Data Streams → Configure Tag Settings → Cross-domain measurement.
  • GTM not loading on app.urwhats.com: The same GTM container (GTM-KBKH4G46) must be installed on both domains.

The Meta Pixel (1367382874855915) is already installed on urwhats.com via src/components/MetaPixel.astro. Meta Pixel handles cross-domain tracking differently (via fbclid parameter and first-party cookies). No additional GTM configuration is needed for Meta — manage pixel events directly through Meta Events Manager or the Meta Pixel code.


Configure the default invoice template in Daftra to match urWave/urWhats branding:

  1. Go to Settings → Invoice Settings → Invoice Template
  2. Configure:
SettingValue
Company NameurWave Company
Trade NameurWhats
LogoUpload urWhats logo (use public/assets/images/logos/urWhats-logo.svg)
Default CurrencySAR (Saudi Riyal)
Default LanguageArabic (primary for Saudi clients)
Secondary LanguageEnglish (for bilingual invoices)
Tax LabelVAT / ضريبة القيمة المضافة
Tax Rate15% (Saudi VAT)
Tax Number (VAT)300075277550003
CR Number7052775355
AddressRiyadh, Kingdom of Saudi Arabia
Phone+966 508 777 669
Emailsales@urwave.com
  1. Enable QR Code on invoices (required by ZATCA for B2C invoices)
  2. Save and preview a sample invoice

Connect PayTabs as the payment gateway (see Section 2.4 for detailed steps):

  1. Settings → Payment Gateways → PayTabs
  2. Enter Profile ID, Server Key, Client Key
  3. Set currency to SAR
  4. Enable: Mada, Visa, Mastercard, Apple Pay, STC Pay
  5. Test with a sandbox invoice before going live

Create subscription billing templates for each plan:

PlanMonthly Price (SAR)Plan ID
Free0 (no invoice)-
Starter3491
Growth9992
Pro1,9993
EnterpriseCustom quote4+

For each paid plan:

  1. Go to Invoices → Recurring Invoices → New Template
  2. Configure:
    • Template Name: urWhats - {Plan Name} Monthly
    • Recurrence: Monthly
    • Start Date: Customer subscription start date
    • Item Description: urWhats {Plan Name} Plan - Monthly Subscription
    • Amount: Plan price (before VAT)
    • Tax: 15% VAT (auto-calculated)
    • Total: Price + VAT (e.g., Starter: 349 + 52.35 = 401.35 SAR)
    • Payment Terms: Due on receipt
    • Auto-send: Enable (sends invoice email automatically on creation date)
  3. Attach PayTabs payment link (Daftra auto-generates this when PayTabs is connected)

Saudi Arabia’s Zakat, Tax and Customs Authority (ZATCA) mandates electronic invoicing in two phases:

Phase 1 (Generation) — Already required:

  • Generate invoices electronically (Daftra handles this natively)
  • Include QR code on all invoices
  • Include seller VAT number, buyer VAT number (if B2B), invoice date, total with VAT

Phase 2 (Integration) — Rolling enforcement by taxpayer group:

  • Invoices must be reported to ZATCA’s Fatoora platform in near-real-time
  • Requires API integration between Daftra and ZATCA
  • Daftra has built-in ZATCA Phase 2 compliance (check Settings → ZATCA Integration)

Steps to enable:

  1. Go to Settings → ZATCA Integration
  2. Enter the Onboarding CSIDs (Compliance and Production) from the ZATCA Fatoora portal
  3. Configure:
    • Solution Name: Daftra
    • Organization Unit: urWave Company
    • VAT Number: 300075277550003
    • CR Number: 7052775355
  4. Run the compliance check (Daftra validates invoice format against ZATCA requirements)
  5. Enable Production Mode once compliance check passes

Note: Check ZATCA’s current enforcement wave schedule at zatca.gov.sa to confirm whether urWave Company’s revenue bracket is currently required to comply with Phase 2. Smaller businesses may have later deadlines.

4.5 Webhook: Payment Received Notification

Section titled “4.5 Webhook: Payment Received Notification”

Set up a webhook to notify app.urwhats.com when a payment is received, enabling automatic plan activation or renewal.

Daftra Webhook Configuration:

  1. Go to Settings → Webhooks (or API Settings → Webhooks)
  2. Create a new webhook:
SettingValue
Eventpayment.created (or invoice.paid)
URLhttps://app.urwhats.com/api/webhooks/daftra
MethodPOST
Content-Typeapplication/json
ActiveYes

Expected Payload:

{
"event": "payment.created",
"data": {
"invoice_id": 12345,
"invoice_number": "INV-2026-0042",
"amount": 401.35,
"amount_before_tax": 349.00,
"tax_amount": 52.35,
"currency": "SAR",
"status": "paid",
"payment_method": "mada",
"customer_id": 678,
"customer_email": "client@example.com",
"paid_at": "2026-03-09T14:30:00+03:00",
"plan_name": "Starter",
"recurring_invoice_id": 99
}
}

Security: HMAC Signature Verification

Daftra signs webhook payloads with an HMAC-SHA256 signature. The receiving endpoint on app.urwhats.com must verify this:

  1. Daftra sends the signature in the X-Daftra-Signature header (or similar — check Daftra’s API docs for exact header name)
  2. The webhook secret is available in Daftra’s webhook settings
  3. On app.urwhats.com, verify the signature before processing:
// Pseudocode for the app.urwhats.com webhook handler
const crypto = require('crypto');
function verifyDaftraWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expectedSignature)
);
}
  1. On successful verification, the app should:

    • Look up the customer by customer_email or customer_id
    • Activate or renew the corresponding plan
    • Log the payment event
    • Return HTTP 200
  2. On failure (invalid signature, unknown customer):

    • Return HTTP 400 or 401
    • Log the error for investigation
    • Do NOT activate any plan

Implementation note: The webhook endpoint (app.urwhats.com/api/webhooks/daftra) must be built in the app.urwhats.com codebase (separate repository). Store the webhook secret as an environment variable (DAFTRA_WEBHOOK_SECRET), never hardcode it.

Sync customer records between Daftra and app.urwhats.com:

Manual approach (initial launch):

  • When a new user registers on app.urwhats.com, manually create a matching customer in Daftra
  • Use the same email address as the unique identifier across both systems
  • Include: company name, contact name, email, phone, VAT number (if B2B)

Automated approach (future):

  • Use the Daftra REST API to auto-create customers when users register on app.urwhats.com
  • Endpoint: POST /api/customers (see Daftra API docs)
  • Trigger: registration_complete event on app.urwhats.com
  • Store the Daftra customer_id in the app.urwhats.com user record for future invoice lookups

Customer fields to sync:

FieldSourceNotes
Emailapp.urwhats.comPrimary identifier
Company NameRegistration formRequired for B2B invoicing
PhoneRegistration formFormat: +966XXXXXXXXX
VAT NumberOptional fieldRequired for B2B tax invoices
Planapp.urwhats.comMaps to recurring invoice template
Languageapp.urwhats.comAR or EN, for invoice language

IntegrationPriorityEffortDependency
GTM Cross-DomainHigh2-3 hoursGTM access, app.urwhats.com GTM install
PayTabs + DaftraHigh1-2 daysDocument submission, PayTabs approval (3-5 days)
Tawk.to Live ChatMedium1-2 hoursCSP header update, account setup
Daftra Recurring BillingMedium3-4 hoursPayTabs connected, plan templates defined
Daftra Webhook → AppLow (future)4-6 hoursApp endpoint built, webhook secret configured
Customer Sync (automated)Low (future)6-8 hoursDaftra API access, app integration

Start with GTM Cross-Domain (quick win, high impact on attribution) and PayTabs account application (long lead time due to document verification). Tawk.to can be added independently at any time. Daftra recurring billing and webhooks depend on PayTabs being live.