ustomers, "", $total_orders, $units_sold ]; $originalDate = DateTime::createFromFormat('Y-m-d', $base_date); $convertedDate = $originalDate->format('m/d/Y'); $this->add_data_for_date($convertedDate, $data_to_export); } catch (Exception $e) { // Log the exception $this->log_error('Error in show_stats function: ' . $e->getMessage()); // Optionally, send an email or perform another form of notification } } function removeElementByValue(array &$array, $valueToRemove): void { $key = array_search($valueToRemove, $array); if ($key !== false) { unset($array[$key]); } $array = array_values($array); } private function log_error($message) { // Get the plugin directory path $plugin_dir_path = plugin_dir_path(__FILE__); // Define the error log file path $log_file = $plugin_dir_path . 'errors.txt'; // Create a timestamp for the log entry $timestamp = date('Y-m-d H:i:s'); // Format the log message $log_message = "{$timestamp}: {$message}\n"; // Write the log message to the file, append if file already exists file_put_contents($log_file, $log_message, FILE_APPEND); // Optionally, you can email the error or perform another form of notification // wp_mail($to, $subject, $log_message); } function add_data_for_date($base_date, $data_to_export) { require __DIR__ . '/google_sheets/vendor/autoload.php'; $client = new \Google_Client(); $data_to_export = array_map(function ($item) { return $item === "" ? Google_Model::NULL_VALUE : $item; }, $data_to_export); // Set up the Google Client $client->setApplicationName('Stats to Google Sheets'); $client->setScopes([\Google_Service_Sheets::SPREADSHEETS]); $client->setAccessType('offline'); $client->setAuthConfig(__DIR__ . '/google_sheets/credentials.json'); $dateObject = DateTime::createFromFormat('m/d/Y', $base_date); $sheet_name = $dateObject->format('F\'y'); $service = new Google_Service_Sheets($client); $spreadsheetId = "184ugNbYIqJBiuzFHk7HgFWww7Gev5vMRW5gWWmwk5l4"; // Your spreadsheet ID $rowNumber = $this->find_row_by_date($service, $spreadsheetId, $base_date, $sheet_name); if ($rowNumber !== null) { $this->update_data_in_row($service, $spreadsheetId, $rowNumber, $data_to_export, $sheet_name); } else { //$this->insert_data_as_new_row($service, $spreadsheetId, $base_date, $data_to_export, $sheet_name); } } function insert_data_as_new_row($service, $spreadsheetId, $date, $data, $sheet_name) { $range = $sheet_name; // Specify the sheet name $valueRange = new Google_Service_Sheets_ValueRange(); // Pre-fill the date column and then add data $rowData = [$date]; $rowData = array_merge($rowData, $data); $valueRange->setValues([$rowData]); // Data array $options = ['valueInputOption' => 'RAW']; // Append the data $service->spreadsheets_values->append($spreadsheetId, $range, $valueRange, $options); } function update_data_in_row($service, $spreadsheetId, $rowNumber, $data, $sheet_name) { $range = $sheet_name . '!F' . $rowNumber; $valueRange = new Google_Service_Sheets_ValueRange(); $valueRange->setValues([$data]); // Data array $options = ['valueInputOption' => 'RAW']; $service->spreadsheets_values->update($spreadsheetId, $range, $valueRange, $options); } function find_row_by_date($service, $spreadsheetId, $inputDate, $sheet_name) { $range = $sheet_name . '!A3:A36'; // Adjust range as needed $response = $service->spreadsheets_values->get($spreadsheetId, $range); $values = $response->getValues(); if (empty($values)) { return null; // No data found } else { foreach ($values as $rowIndex => $row) { if (!empty($row[0])) { $date = DateTime::createFromFormat('l, F d, Y', $row[0]); $date_formated = $date->format('m/d/Y'); if ($row[0] == $inputDate || $inputDate == $date_formated) { return $rowIndex + 3; // +2 to align with the spreadsheet's row numbering } } } } return null; // Date not found } // Activation Hook public function activate() { $environment = get_option('warehouse_export_environment', 'sandbox'); $is_sandbox = ($environment === 'sandbox'); if ($is_sandbox) return; if (!wp_next_scheduled('export_stats_daily_event')) { $timestamp = strtotime('tomorrow 5:00 AM'); wp_schedule_event($timestamp, 'daily', 'export_stats_daily_event'); } if (!wp_next_scheduled('export_openai_daily_event')) { $timestamp = strtotime('tomorrow 5:30 AM'); wp_schedule_event($timestamp, 'daily', 'export_openai_daily_event'); } } public function export_openai_stats_to_sheets() { global $wpdb; $table_name = $wpdb->prefix . 'openai_crawlers'; $results = $wpdb->get_results(" SELECT crawler_type, LEFT(page_url, CASE WHEN LOCATE('?', page_url) > 0 THEN LOCATE('?', page_url) - 1 ELSE LENGTH(page_url) END ) AS clean_url, COUNT(*) as view_count FROM $table_name GROUP BY clean_url, crawler_type ORDER BY view_count DESC "); if (empty($results)) { $this->log_error('No OpenAI crawler data found for export.'); return; } // Prepare data $sheet_data = []; $sheet_data[] = ['Crawler Type', 'Page URL', 'Views']; // Header row foreach ($results as $row) { $sheet_data[] = [$row->crawler_type, $row->clean_url, $row->view_count]; } // Export $this->send_openai_data_to_sheets($sheet_data, 'OpenAI Crawlers'); } private function send_openai_data_to_sheets($data, $sheetName) { require __DIR__ . '/google_sheets/vendor/autoload.php'; $client = new \Google_Client(); $client->setApplicationName('OpenAI Export'); $client->setScopes([\Google_Service_Sheets::SPREADSHEETS]); $client->setAccessType('offline'); $client->setAuthConfig(__DIR__ . '/google_sheets/credentials.json'); $service = new Google_Service_Sheets($client); $spreadsheetId = '1NCtlM0_QblXBIWmxqKc8u8eJrl_0zwIExcoYrbueBXM'; // Clear the full sheet first $range = $sheetName . '!A1:Z1000'; $service->spreadsheets_values->clear($spreadsheetId, $range, new Google_Service_Sheets_ClearValuesRequest()); // Write the main data starting at A1 (row 1) $body = new Google_Service_Sheets_ValueRange(['values' => $data]); $params = ['valueInputOption' => 'RAW']; $service->spreadsheets_values->update($spreadsheetId, $sheetName . '!A1', $body, $params); // Format timestamp: Tue, May 27 2025 — 18:13 $now = new DateTime('now', new DateTimeZone('UTC')); $now->modify('+3 hours'); $formattedTime = $now->format('D, M j Y — H:i'); // Write timestamp directly to D1 $timestampBody = new Google_Service_Sheets_ValueRange([ 'range' => $sheetName . '!D1', 'values' => [['Last updated: ' . $formattedTime]] ]); $service->spreadsheets_values->update( $spreadsheetId, $timestampBody->range, $timestampBody, ['valueInputOption' => 'RAW'] ); } // Deactivation Hook public function deactivate() { $timestamp = wp_next_scheduled('export_stats_hourly_event'); wp_unschedule_event($timestamp, 'export_stats_hourly_event'); $timestamp = wp_next_scheduled('export_stats_daily_event'); wp_unschedule_event($timestamp, 'export_stats_daily_event'); } /************************************************************/ /* HPOS-AWARE HELPER FUNCTIONS */ /************************************************************/ // 1) Safely get an order’s GMT date from old or new tables, returning a string (e.g. "2023-04-05 10:22:01") private function get_order_date_gmt($order_id, $post_type = 'shop_order') { global $wpdb; // Try old wp_posts table $order_date_gmt = $wpdb->get_var( $wpdb->prepare( "SELECT post_date_gmt FROM {$wpdb->posts} WHERE ID = %d AND post_type = %s", $order_id, $post_type ) ); if ($order_date_gmt) { return $order_date_gmt; } // Check if HPOS table exists $tbl_orders = $wpdb->prefix . 'wc_orders'; $tbl_exists = $wpdb->get_var("SHOW TABLES LIKE '{$tbl_orders}'"); if ($tbl_exists === $tbl_orders) { // Try to fetch from HPOS table $sql = $wpdb->prepare( "SELECT date_created_gmt FROM {$tbl_orders} WHERE id = %d", $order_id ); $order_date_gmt = $wpdb->get_var($sql); } return $order_date_gmt; } // 2) Safely get meta from old or new order-meta tables, combining if needed. // Returns an associative array, e.g. [ '_order_total' => '123.45', ... ] private function get_order_meta($order_id, $meta_keys = array()) { global $wpdb; $meta_array = []; // Attempt old postmeta if (!empty($meta_keys)) { $placeholders = implode(',', array_fill(0, count($meta_keys), '%s')); $params = array_merge([$order_id], $meta_keys); $old_results = $wpdb->get_results( $wpdb->prepare( " SELECT meta_key, meta_value FROM {$wpdb->postmeta} WHERE post_id = %d AND meta_key IN ($placeholders)", $params ), OBJECT_K ); if (!empty($old_results)) { foreach ($old_results as $row) { $meta_array[$row->meta_key] = $row->meta_value; } } } // Now also grab from HPOS if table exists, so we *combine* (in case partial migration) $tbl = $wpdb->prefix . 'wc_orders_meta'; $tbl_exists = $wpdb->get_var("SHOW TABLES LIKE '{$tbl}'"); if ($tbl_exists == $tbl) { if (!empty($meta_keys)) { $placeholders = implode(',', array_fill(0, count($meta_keys), '%s')); $params = array_merge([$order_id], $meta_keys); $new_results = $wpdb->get_results( $wpdb->prepare( " SELECT meta_key, meta_value FROM {$tbl} WHERE order_id = %d AND meta_key IN ($placeholders)", $params ), OBJECT_K ); if (!empty($new_results)) { foreach ($new_results as $row) { $meta_array[$row->meta_key] = $row->meta_value; } } } } return $meta_array; } // 3) Safely sum up line-item quantities from old or new table, combining them if found in both private function get_order_line_item_qty_sum($order_id) { global $wpdb; $total_qty = 0; $table_items = $wpdb->prefix . 'woocommerce_order_items'; $table_meta = $wpdb->prefix . 'woocommerce_order_itemmeta'; // Check if tables exist $items_table_exists = $wpdb->get_var("SHOW TABLES LIKE '{$table_items}'") === $table_items; $meta_table_exists = $wpdb->get_var("SHOW TABLES LIKE '{$table_meta}'") === $table_meta; if (!$items_table_exists || !$meta_table_exists) { return 0; } // Grab individual line items for debugging $results = $wpdb->get_results($wpdb->prepare(" SELECT oim.meta_value AS qty, oi.order_item_id FROM {$table_items} AS oi INNER JOIN {$table_meta} AS oim ON oi.order_item_id = oim.order_item_id WHERE oi.order_id = %d AND oi.order_item_type = 'line_item' AND oim.meta_key = '_qty' ", $order_id)); if (empty($results)) { return 0; } foreach ($results as $row) { $qty = intval($row->qty); $total_qty += $qty; } return $total_qty; } public function log_message($data) { if (!function_exists('WP_Filesystem')) { require_once ABSPATH . 'wp-admin/includes/file.php'; } WP_Filesystem(); global $wp_filesystem; $plugin_dir = plugin_dir_path(__FILE__); $log_file = $plugin_dir . 'my_log.txt'; $current_time = current_time('Y-m-d H:i:s'); // Format the data appropriately if (is_array($data) || is_object($data)) { $formatted_data = print_r($data, true); } else { $formatted_data = (string)$data; } $log_entry = "[{$current_time}] {$formatted_data}\n"; if ($wp_filesystem->exists($log_file)) { $existing_content = $wp_filesystem->get_contents($log_file); $wp_filesystem->put_contents($log_file, $existing_content . $log_entry); } else { $wp_filesystem->put_contents($log_file, $log_entry); } } } // Initialize the plugin $export_stats = new Export_stats(); Guide to Perfectly Trimmed Men's Eyebrows | Particle
Free Shipping + 30 Day Money Back Guarantee

Magazine

Men’s Eyebrows: How to Trim Your Eyebrows for a More Attractive Look

author
Posted by

Brian Melville

Are you looking to neaten up your brows?

Currently, thick brows are in, which is great news for guys, because, unlike women, our eyebrows get bushier with age.

But, this doesn’t mean you should have unkempt brows.

Although women have been tending to their eyebrows for millennia, it’s often men’s eyebrows that are most in need of a firm hand. Our higher testosterone levels mean more hair growth, and bushier, more unruly brows.

What’s more, it doesn’t take all that much to trim your eyebrows. In a few simple steps, you can neaten up your brows and get them looking on point. However, you do want to make sure you don’t take things too far, otherwise, you might end up looking like the male counterpart of Angelina Jolie in the 90s.

Read on to find out how to trim your brows for a fresh look.

Start With a Clean Face

One of the first tips for trimming men’s eyebrows is to start with a freshly washed face. As a general rule of thumb, it’s always better to remove hair when your skin is clean.

One of the best times for grooming your brows is after a hot shower, especially if you going to try men’s eyebrow waxing or undertake some tweezing. The hot water will help to open up the pores and hair follicles so that the hair strands can come out easily.

Alternatively, if you don’t have time for a shower you can also just wash your face well with warm water.

Brush Your Brows Upwards

The next step to grooming men’s eyebrows is to brush your brows upwards. The easiest way to do this is with a clean mascara wand or an eyebrow brush, such as the ones found on the lids of eye pencils.

If you don’t have either of these—or can’t snag one from a girlfriend or better half’s vanity bag— you can also use a toothbrush or a fine comb.

Hair Above the Nose Is a No-Go

If you’re not sure which areas to address first, a great place to start is above the nose. Hair above the nose is a general no-go, unless you’re after the monobrow look.

Incidentally, monobrows were a prized aesthetic back in Ancient Greece and Egyptian times, when it was considered a symbol of high intelligence.

But, if you’re happy to demonstrate your intelligence in other ways, you’re probably better off tweezing any excess hair that might be growing over your nose.

If you want to try out men’s eyebrow waxing, the monobrow area is a perfect place to practice as it’s usually easier to tackle than the areas under your brows.

Tweeze the Outliers

Next, take a pair of tweezers and get to work removing any stray hairs that are obvious outliers from your brows.

If you have never taken a pair of tweezers to your face before here are some tips:

  • Grip the hair tightly
  • Hold the skin taut with one finger
  • Pull the hair out with a sharp, quick action

Whatever you do, don’t try pulling the hair out slowly as this will make things more painful.

Once you have removed any stray hairs that are growing out of your defined brow area, you’ll probably find that your eyebrows already look quite a lot neater.

Undertake Shape Changes With Care

If you want to change the shape of your brows, we recommend that you do this with great care. Most people find that cleaning up stray hairs will define the natural brow shape, which is often the shape that will most complement your face.

Changes to your eyebrow shape can easily go wrong. They might not fit with your features, and they are also pretty hard to pull off at home.

Additionally, the best men’s eyebrow shape looks are pretty natural. Simply getting things neatened up is usually all that one needs to get your brows looking sharp.

However, if you do want to make serious changes to your brows, the best thing to do is go to an expert in men’s eyebrow waxing. They will be able to advise you as to the best men’s eyebrow shape for your face and walk you through some attractive men’s eyebrows options.

Gently Trim the Tops

To finish things off and keep long hairs within your brows from going astray, the next step is to gently trim the tops. If you need to, give your brows another comb upwards, and then take a small pair of scissors or a men’s eyebrow trimmer and get to work.

The idea is to simply trim off the tips of any extra-long hairs. You don’t want to take off too much length, as this can make your brows look sparse and patchy.

This is especially important for the hairs at the ends of your eyebrows. When these hairs lie in their usual growth pattern they can help to elongate your brows, which opens up your eyes. If you trim these too short, this can shorten your overall brows.

Ideally, you should only remove excess length, so that should you rub your eyes or forehead, longer brown hairs won’t go sticking up all over the place.

If you don’t feel comfortable with this step you can also go to a beautician or barber who offers a men’s eyebrows line cut. A lot of barbers offer things like ear hair trimming and brow top trims.

Aftercare

After you have neatened up your brows, you can splash your face with cold water. This will help to soothe your skin and rinse off any hairs that landed on your face.

After this, you can finish things off with a good men’s face cream to hydrate and soothe.

Sleek Men’s Eyebrows Have Never Been So In

Having neatly trimmed, sleek men’s eyebrows can freshen up your face and up your style ante within minutes. Okay, if this is your first time, you might take more than a couple of minutes—but it is still a quick and easy step to add to your grooming arsenal.

Speaking of your grooming arsenal, are you looking for men’s care products that can do it all in minutes? Here at Particle, we combine high-grade ingredients with cutting-edge technology to create products for men that work. We are so confident in our products that we even offer a money-back guarantee.

Shop the range of Particle products today.