SendGrid Custom Integration WP

User
How to integrate sendgrid marketing newsleeter programtticall yin wordpress without Marketing->Signup form imframe ON custom form
Assistant
To **integrate SendGrid Marketing Campaigns (newsletter)** programmatically in WordPress **without using the Signup Form iframe** (i.e., using a **custom form**), follow this secure and flexible approach using the **SendGrid API**:

### ✅ Goal:
When a user submits a custom form on your WordPress site, their email (and other details) should be **added to a SendGrid Marketing List** using the **SendGrid v3 API** — all done via PHP or AJAX, **no iframe**.

### ✅ Steps to Integrate Custom Newsletter Form with SendGrid

#### 🔹 1. **Create a Marketing List in SendGrid**

– Go to [SendGrid → Marketing → Contacts](https://app.sendgrid.com/marketing/contacts)
– Click **"Create List"** and name it (e.g., `Website Subscribers`)
– Note down the List ID (you'll fetch this via API in the next steps)

#### 🔹 2. **Generate SendGrid API Key**

– Go to [SendGrid → Settings → API Keys](https://app.sendgrid.com/settings/api_keys)
– Create a new key with **Full Access** to "Marketing"
– Save this API key securely (we’ll use it in code)

#### 🔹 3. **Create a Custom Form in WordPress**

Example form (use in a page, widget, or template):

<form id="newsletter-form">
  <input type="email" name="email" placeholder="Enter your email" required />
  <input type="text" name="first_name" placeholder="First Name" />
  <button type="submit">Subscribe</button>
  <div id="newsletter-result"></div>
</form>

#### 🔹 4. **Add AJAX Submission to WordPress (Enqueue JS)**

Add to your theme’s JS (or inline):

jQuery(document).ready(function ($) {
  $('#newsletter-form').on('submit', function (e) {
    e.preventDefault();

    var formData = $(this).serialize();

    $.post({
      url: newsletter_form_ajax.ajax_url,
      data: {
        action: 'sendgrid_subscribe',
        formData: formData,
      },
      success: function (response) {
        $('#newsletter-result').html(response.message);
      },
    });
  });
});

Add this enqueue in your `functions.php`:

add_action('wp_enqueue_scripts', function () {
    wp_enqueue_script('newsletter-form', get_template_directory_uri() . '/js/newsletter.js', ['jquery'], null, true);
    wp_localize_script('newsletter-form', 'newsletter_form_ajax', ['ajax_url' => admin_url('admin-ajax.php')]);
});

#### 🔹 5. **Handle AJAX in `functions.php` (Server-side Call to SendGrid)**

add_action('wp_ajax_sendgrid_subscribe', 'handle_sendgrid_subscribe');
add_action('wp_ajax_nopriv_sendgrid_subscribe', 'handle_sendgrid_subscribe');

function handle_sendgrid_subscribe() {
    parse_str($_POST['formData'], $data);

    $email = sanitize_email($data['email']);
    $first_name = sanitize_text_field($data['first_name'] ?? '');

    if (!is_email($email)) {
        wp_send_json(['success' => false, 'message' => 'Invalid email']);
    }

    $apiKey = 'YOUR_SENDGRID_API_KEY';
    $listId = 'YOUR_SENDGRID_LIST_ID';

    $contactData = [
        'list_ids' => [$listId],
        'contacts' => [[
            'email' => $email,
            'first_name' => $first_name,
        ]]
    ];

    $response = wp_remote_post('https://api.sendgrid.com/v3/marketing/contacts', [
        'headers' => [
            'Authorization' => 'Bearer ' . $apiKey,
            'Content-Type' => 'application/json',
        ],
        'body' => json_encode($contactData),
    ]);

    if (is_wp_error($response)) {
        wp_send_json(['success' => false, 'message' => 'Request failed']);
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);

    if (isset($body['job_id'])) {
        wp_send_json(['success' => true, 'message' => 'Thank you for subscribing!']);
    } else {
        wp_send_json(['success' => false, 'message' => 'Unable to subscribe']);
    }
}

### 🔐 Security Tips

– Store the SendGrid API key securely, optionally using `wp-config.php`.
– Rate-limit or add CAPTCHA to prevent spam.

### ✅ Final Output

A fully custom newsletter form that:
– Submits via AJAX
– Adds users directly to your SendGrid Marketing List
– Doesn’t require iframe or Marketing → Signup Form builder

If you need this to work via REST API instead of `admin-ajax.php` (for headless WordPress or JS apps), I can help you set that up too.

Would you like a plugin version of this for reuse across projects?

User
YOUR_SENDGRID_LIST_ID what is this and how We will get this
Assistant
Great question! Here's how you get your **`YOUR_SENDGRID_LIST_ID`** – which is the ID of the **Marketing List** you want to add users to.

### ✅ What is `YOUR_SENDGRID_LIST_ID`?

This is the **unique ID** of a list (e.g., "Website Subscribers") created inside **SendGrid Marketing Campaigns**.
It's required when using the **SendGrid Marketing API** to add contacts programmatically.

### 🔍 How to Get the List ID?

#### 🔹 Option 1: **Using the SendGrid API** (Recommended)

SendGrid doesn’t show the List ID in the UI directly, so we use the **List API**:

##### ✅ Make this cURL request (replace your actual API key):

curl --request GET 
  --url https://api.sendgrid.com/v3/marketing/lists 
  --header "Authorization: Bearer YOUR_SENDGRID_API_KEY" 
  --header "Content-Type: application/json"

##### 🧠 Response Example:

{
  "result": [
    {
      "id": "9b2d7a3f-8f63-4f8b-a455-xxxxx",
      "name": "Website Subscribers",
      ...
    }
  ]
}

➡️ Copy the `id` field — that is your **`YOUR_SENDGRID_LIST_ID`**

#### 🔹 Option 2: **Use Postman (No Coding)**

1. Open [Postman](https://www.postman.com/)
2. Create a `GET` request to:

https://api.sendgrid.com/v3/marketing/lists

3. Add Header:
– `Authorization: Bearer YOUR_SENDGRID_API_KEY`
– `Content-Type: application/json`

4. Hit **Send** — you'll get a list of all your lists with `id` values.

#### 🔹 Option 3: Create a New List and Capture ID Immediately

You can also create a list via API and note the returned `id`:

curl --request POST 
  --url https://api.sendgrid.com/v3/marketing/lists 
  --header "Authorization: Bearer YOUR_SENDGRID_API_KEY" 
  --header "Content-Type: application/json" 
  --data '{
    "name": "Website Subscribers"
  }'

### 📌 Pro Tip

Once you get the ID, store it in `wp-config.php` for easy use:

define('SENDGRID_LIST_ID', '9b2d7a3f-8f63-4f8b-a455-xxxx');

Then in your code:

$listId = constant('SENDGRID_LIST_ID');

Would you like me to generate a ready-to-run API snippet or Postman collection for you?

User
we have this
/contacts/lists/f3eaa89e-b043-4652-9b37-7eb45501b7b6
Assistant
Perfect! The part after `/contacts/lists/` is your **List ID**.

### ✅ Your `YOUR_SENDGRID_LIST_ID` is:

f3eaa89e-b043-4652-9b37-7eb45501b7b6

### 🔧 How to Use in Your WordPress Code:

Replace this:

$listId = 'YOUR_SENDGRID_LIST_ID';

With this:

$listId = 'f3eaa89e-b043-4652-9b37-7eb45501b7b6';

And you’re all set! 🎉

This will ensure contacts added via your custom form go directly into the right **SendGrid Marketing List**.

Let me know if you want to add more fields like `last_name`, `custom_fields`, or tag contacts — I can help with that too.

User
public function handle_newsletter_form() {
check_ajax_referer('newsletter_nonce', 'nonce');

$email = sanitize_email($_POST['email']);
$regular = sanitize_text_field($_POST['regular']);
$specific = sanitize_text_field($_POST['specific']);

$sendgrid_api_key = 'SG.Et-F1hGBQ924bE-jjmTkccQPGLudM';
$listId = 'f3eaa89e-b043-4652-9b37-7eb45501b7b6';
$body = [
'personalizations' => [[
'to' => [['email' => 'rahulratnam@nethues.com']],
'subject' => 'New Newsletter Signup',
]],
'from' => ['email' => 'no-reply@professor.com'],
'content' => [[
'type' => 'text/plain',
'value' => "New Signup:nEmail: $emailnRegular: $regularnSpecific: $specific",
]]
];

$response = wp_remote_post('https://api.sendgrid.com/v3/mail/send', [
'headers' => [
'Authorization' => 'Bearer ' . $sendgrid_api_key,
'Content-Type' => 'application/json',
],
'body' => wp_json_encode($body),
]);

// echo '';
// print_r($response);
// die;

if (is_wp_error($response)) {
wp_send_json(['message' => '❌ Failed to send email.']);
}

wp_send_json(['message' => '✅ Thank you! You are signed up.']);
exit;
}
adjust in above code

Assistant
You're **currently sending an email via SendGrid**, but you also want to **add the user to your SendGrid Marketing List** (`f3eaa89e-b043-4652-9b37-7eb45501b7b6`) at the same time.

Here’s how to **adjust your `handle_newsletter_form()` function** to:

1. ✅ Add the contact to SendGrid Marketing List.
2. 📧 Send notification email to admin.

### ✅ Final Updated Code

public function handle_newsletter_form() {
    check_ajax_referer('newsletter_nonce', 'nonce');

    $email    = sanitize_email($_POST['email']);
    $regular  = sanitize_text_field($_POST['regular']);
    $specific = sanitize_text_field($_POST['specific']);

    $sendgrid_api_key = 'SG.Et-F1hGBQ924bE-jjmTkccQPGLudM';
    $listId = 'f3eaa89e-b043-4652-9b37-7eb45501b7b6';

    // ✅ 1. Add contact to SendGrid List
    $contactData = [
        'list_ids' => [$listId],
        'contacts' => [[
            'email' => $email,
            'custom_fields' => [
                // Optional: if you have custom fields, add them here by custom field ID
                // e.g. 'e1_T' => $regular,
                //       'e2_T' => $specific
            ]
        ]]
    ];

    $add_response = wp_remote_post('https://api.sendgrid.com/v3/marketing/contacts', [
        'headers' => [
            'Authorization' => 'Bearer ' . $sendgrid_api_key,
            'Content-Type'  => 'application/json',
        ],
        'body' => wp_json_encode($contactData),
    ]);

    if (is_wp_error($add_response)) {
        wp_send_json(['message' => '❌ Failed to add to newsletter list.']);
    }

    // ✅ 2. Send admin notification email
    $emailBody = [
        'personalizations' => [[
            'to' => [['email' => 'rahulratnam@nethues.com']],
            'subject' => 'New Newsletter Signup',
        ]],
        'from' => ['email' => 'no-reply@professor.com'],
        'content' => [[
            'type' => 'text/plain',
            'value' => "New Signup:nEmail: $emailnRegular: $regularnSpecific: $specific",
        ]]
    ];

    $mail_response = wp_remote_post('https://api.sendgrid.com/v3/mail/send', [
        'headers' => [
            'Authorization' => 'Bearer ' . $sendgrid_api_key,
            'Content-Type'  => 'application/json',
        ],
        'body' => wp_json_encode($emailBody),
    ]);

    if (is_wp_error($mail_response)) {
        wp_send_json(['message' => '✅ Added to list, but failed to send admin email.']);
    }

    wp_send_json(['message' => '✅ Thank you! You are signed up.']);
    exit;
}

### 📝 Optional (Add Custom Fields)

If you want to store `regular` and `specific` as custom fields in SendGrid:

1. Go to **SendGrid → Marketing → Contacts → Custom Fields**
2. Create two new fields: e.g. `regular_interest`, `specific_topic`
3. Note down their **custom field IDs** (looks like `e1_T`, `e2_T` etc.)
4. Then adjust:

'custom_fields' => [
    'e1_T' => $regular,
    'e2_T' => $specific
]

Let me know if you want to make this form GDPR-compliant or add double opt-in too.

User
dont want to sen email from this just send contact to sendgrid
Assistant
Perfect — to **only send the contact to SendGrid (without sending an email)**, just remove the email-related part from your function.

Here’s your **cleaned and adjusted version**:

### ✅ Final Code – Only Send Contact to SendGrid List

public function handle_newsletter_form() {
    check_ajax_referer('newsletter_nonce', 'nonce');

    $email    = sanitize_email($_POST['email']);
    $regular  = sanitize_text_field($_POST['regular']);
    $specific = sanitize_text_field($_POST['specific']);

    $sendgrid_api_key = 'SG.Et-F1hGBQ924bE-jjmTkccQPGLudM';
    $listId = 'f3eaa89e-b043-4652-9b37-7eb45501b7b6';

    // ✅ Prepare contact data
    $contactData = [
        'list_ids' => [$listId],
        'contacts' => [[
            'email' => $email,
            'custom_fields' => [
                // If you've created custom fields in SendGrid, add them here using field IDs
                // 'e1_T' => $regular,
                // 'e2_T' => $specific
            ]
        ]]
    ];

    // ✅ Send to SendGrid
    $response = wp_remote_post('https://api.sendgrid.com/v3/marketing/contacts', [
        'headers' => [
            'Authorization' => 'Bearer ' . $sendgrid_api_key,
            'Content-Type'  => 'application/json',
        ],
        'body' => wp_json_encode($contactData),
    ]);

    if (is_wp_error($response)) {
        wp_send_json(['message' => '❌ Failed to subscribe. Please try again later.']);
    }

    wp_send_json(['message' => '✅ Thank you! You are now subscribed.']);
    exit;
}

### 🧠 Notes:

– This only **adds the contact** to your SendGrid **Marketing List**.
– `custom_fields` section is optional — add if you have them set up in SendGrid.
– No email will be sent from your server or SendGrid.

Let me know if you want:
– custom field IDs added,
– confirmation messages styled,
– or the same logic implemented via REST API for headless setups.

User
{

"data": {
"headers": {},
"body": "",
"response": {
"code": 405,
"message": "Method Not Allowed"
},
"cookies": [],
"filename": null,
"http_response": {
"data": null,
"headers": null,
"status": null
}
}
}

abo e the respons ei get

Assistant
A `405 Method Not Allowed` error means you're **using the wrong HTTP method** for the endpoint.

In your case, you're trying to **add a contact** to SendGrid using this endpoint:

https://api.sendgrid.com/v3/marketing/contacts

This endpoint **requires a `PUT` method**, not `POST`.

### ✅ Fix

Update your `wp_remote_post()` to use the correct method by changing it to `wp_remote_request()` with `'method' => 'PUT'`.

### 🔧 Updated Code:

$response = wp_remote_request('https://api.sendgrid.com/v3/marketing/contacts', [
    'method'  => 'PUT', // ✅ Correct method
    'headers' => [
        'Authorization' => 'Bearer ' . $sendgrid_api_key,
        'Content-Type'  => 'application/json',
    ],
    'body'    => wp_json_encode($contactData),
]);

### ✅ Full Working Snippet (Corrected)

public function handle_newsletter_form() {
    check_ajax_referer('newsletter_nonce', 'nonce');

    $email    = sanitize_email($_POST['email']);
    $regular  = sanitize_text_field($_POST['regular']);
    $specific = sanitize_text_field($_POST['specific']);

    $sendgrid_api_key = 'SG.Et-F1hGBQ924bE-jjmTkccQPGLudM';
    $listId = 'f3eaa89e-b043-4652-9b37-7eb45501b7b6';

    $contactData = [
        'list_ids' => [$listId],
        'contacts' => [[
            'email' => $email,
            'custom_fields' => [
                // Uncomment if custom fields set up in SendGrid
                // 'e1_T' => $regular,
                // 'e2_T' => $specific
            ]
        ]]
    ];

    $response = wp_remote_request('https://api.sendgrid.com/v3/marketing/contacts', [
        'method'  => 'PUT', // ✅ Use PUT instead of POST
        'headers' => [
            'Authorization' => 'Bearer ' . $sendgrid_api_key,
            'Content-Type'  => 'application/json',
        ],
        'body'    => wp_json_encode($contactData),
    ]);

    if (is_wp_error($response)) {
        wp_send_json(['message' => '❌ Failed to subscribe.']);
    }

    wp_send_json(['message' => '✅ Thank you! You are now subscribed.']);
    exit;
}

Let me know if you want to:
– handle duplicate emails gracefully,
– tag users,
– or add GDPR compliance.

User
Now
"data": {
"headers": {},
"body": "{"errors":[{"field":"","message":"invalid input"}]}",
"response": {
"code": 400,
"message": "Bad Request"
},
"cookies": [],
"filename": null,
"http_response": {
"data": null,
"headers": null,
"status": null
}
}
}
Assistant
You're now getting:

400 Bad Request
"message": "invalid input"

This means the payload (`$contactData`) you're sending to the SendGrid API is malformed or invalid.

### ✅ Let's Debug It Step-by-Step:

#### 1. ✅ **Check your `$contactData` structure**

Your `$contactData` **must** be a **valid JSON with required fields**, like this:

$contactData = [
    'list_ids' => ['f3eaa89e-b043-4652-9b37-7eb45501b7b6'],
    'contacts' => [
        [
            'email' => $email,
            // Only include fields if they have valid values
            // 'first_name' => 'Neeraj',
            // 'custom_fields' => [
            //     'e1_T' => $regular,
            //     'e2_T' => $specific
            // ]
        ]
    ]
];

If **`$email` is empty or invalid**, or if **`custom_fields` contain wrong keys**, you'll get `400`.

### 🔍 Let's validate:

Here’s a working minimal example:

#### ✅ Final Minimal Working Version:

public function handle_newsletter_form() {
    check_ajax_referer('newsletter_nonce', 'nonce');

    $email    = sanitize_email($_POST['email']);
    if (!is_email($email)) {
        wp_send_json(['message' => '❌ Invalid email address.']);
    }

    $sendgrid_api_key = 'SG.Et-F1hGBQ924bE-jjmTkccQPGLudM';
    $listId = 'f3eaa89e-b043-4652-9b37-7eb45501b7b6';

    $contactData = [
        'list_ids' => [$listId],
        'contacts' => [
            [
                'email' => $email
            ]
        ]
    ];

    $response = wp_remote_request('https://api.sendgrid.com/v3/marketing/contacts', [
        'method'  => 'PUT',
        'headers' => [
            'Authorization' => 'Bearer ' . $sendgrid_api_key,
            'Content-Type'  => 'application/json',
        ],
        'body'    => wp_json_encode($contactData),
    ]);

    if (is_wp_error($response)) {
        wp_send_json(['message' => '❌ Failed to connect to SendGrid.']);
    }

    $body = json_decode(wp_remote_retrieve_body($response), true);

    if (isset($body['errors'])) {
        wp_send_json(['message' => '❌ SendGrid error: ' . $body['errors'][0]['message']]);
    }

    wp_send_json(['message' => '✅ Thank you! You are now subscribed.']);
    exit;
}

### 📌 If You Still Get Error

Log the `$contactData` just before the request:

error_log(print_r($contactData, true));

Also, log SendGrid's response:

error_log(wp_remote_retrieve_body($response));

### ✅ Common Causes of 400:
| Cause | Fix |
|——|—–|
| Missing or invalid email | Check with `is_email($email)` |
| `list_ids` is empty or invalid | Double-check your list ID |
| `custom_fields` keys are not created in SendGrid | Only use custom field IDs you've created (e.g. `e1_T`) |
| Sending null/empty values | Strip them before sending |

Let me know if you want to include custom fields next — but let's get the base working first.

User
$contactData = [
'list_ids' => [$listId],
'contacts' => [[
'email' => $email,
'custom_fields' => [
// If you've created custom fields in SendGrid, add them here using field IDs
// 'e1_T' => $regular,
// 'e2_T' => $specific
]
]]
];
Assistant
Thanks! Based on that snippet, you're **including `custom_fields` even though it’s empty**, which can **cause a `400 Bad Request: invalid input` error** in SendGrid's API.

### ✅ Fix: Only include `custom_fields` **if values and field IDs exist**

SendGrid requires **valid custom field IDs** like `e1_T`, `e2_T`, etc., and will reject the payload if:

– the keys don't exist in your SendGrid dashboard
– the values are `null` or empty
– the structure is wrong

### ✅ Best Practice Code:

$contact = [
    'email' => $email
];

// OPTIONAL: Add custom fields if you have them configured in SendGrid
$custom_fields = [];
if (!empty($regular)) {
    $custom_fields['e1_T'] = $regular; // replace with your actual custom field ID for 'regular'
}
if (!empty($specific)) {
    $custom_fields['e2_T'] = $specific; // replace with your actual custom field ID for 'specific'
}

if (!empty($custom_fields)) {
    $contact['custom_fields'] = $custom_fields;
}

$contactData = [
    'list_ids' => [$listId],
    'contacts' => [$contact]
];

### 🔍 Find Your Actual Custom Field IDs:

Go to:

– **SendGrid > Marketing > Contacts > Custom Fields**
– Note the **field IDs** that look like `e1_T`, `e2_T`, etc.
– Use them in the `custom_fields` array as keys

### ✅ Final JSON Example (Valid Payload)

{
  "list_ids": ["f3eaa89e-b043-4652-9b37-7eb45501b7b6"],
  "contacts": [
    {
      "email": "user@example.com",
      "custom_fields": {
        "e1_T": "General Updates",
        "e2_T": "Health Tips"
      }
    }
  ]
}

Let me know your actual field IDs if you want help hardcoding them in safely. Once that’s fixed, the `400` will disappear.

User
KiyOh API get toTAL Reviews
Assistant
To **get the total number of reviews using the KiyOh API**, you'll typically use their **public API** endpoint which provides aggregated data such as **total reviews**, **average score**, etc.

### ✅ Basic KiyOh API Endpoint to Get Reviews Summary

**Example GET endpoint:**

https://www.kiyoh.com/v1/publication/review/external/location?locationId=YOUR_LOCATION_ID

> 🟡 Replace `YOUR_LOCATION_ID` with your actual KiyOh company/location ID (you can find this in your KiyOh account or embedded widget snippet).

### 🔍 Example Response:

{
  "totalReviews": 234,
  "averageRating": 8.9,
  "locationId": 12345,
  ...
}

– **`totalReviews`**: 👈 This is what you’re looking for — total number of reviews.
– **`averageRating`**: Overall rating.
– Other fields include breakdown by date, sentiment, etc.

### ✅ Sample Code (PHP + WordPress style)

$locationId = 'YOUR_LOCATION_ID';
$response = wp_remote_get("https://www.kiyoh.com/v1/publication/review/external/location?locationId={$locationId}");

if (is_wp_error($response)) {
    return 'Error fetching KiyOh data.';
}

$body = json_decode(wp_remote_retrieve_body($response), true);

if (isset($body['totalReviews'])) {
    echo 'Total Reviews: ' . $body['totalReviews'];
} else {
    echo 'No review data available.';
}

### 🔐 Do You Need an API Key?

– For **public summary data**, **no authentication is needed** (i.e., total reviews and rating).
– For **detailed review data or posting reviews**, you need **API credentials (API key + location ID)** — available to paid customers.

### ✅ Example Output

Total Reviews: 172

Let me know if:
– You want to **display this on your WordPress site with a shortcode**
– Or fetch **individual review data (with date, stars, etc.)**
– Or use **cURL, jQuery, or REST API** instead of `wp_remote_get`

Leave a Comment

Your email address will not be published. Required fields are marked *