diff --git a/docs/AnalyticsTags.md b/docs/AnalyticsTags.md new file mode 100644 index 0000000..657e05d --- /dev/null +++ b/docs/AnalyticsTags.md @@ -0,0 +1,63 @@ +Mailgun - Analytics Tags +==================== + +This is the Mailgun Ruby *Analytics Tags* utilities. + +The below assumes you've already installed the Mailgun Ruby SDK in to your +project. If not, go back to the master README for instructions. It currently supports +all calls except credentials. + +--- + +Mailgun allows you to tag your email with unique identifiers. Tags are visible via our analytics tags API endpoint. + +You can view additional samples in the [analytics_tags_spec.rb](/spec/integration/analytics_tags_spec.rb) +or the Analytics Tags client API in [analytics_tags.rb](/lib/mailgun/tags/analytics_tags.rb). + +Usage +----- + +To get an instance of the Analytics Tags client: + +```ruby +require 'mailgun' + +mg_client = Mailgun::Client.new('your-api-key', 'mailgun-api-host', 'v1') +tags = Mailgun::AnalyticsTags.new(mg_client) +```` +--- +Update account tag: +```ruby +tags.update('name-of-tag-to-update', 'updated tag description') +``` +--- + +Post query to list account tags or search for single tag: +```ruby +options = { + pagination: { + sort: 'lastseen:desc', + limit: 10 + }, + include_subaccounts: true +} + +tags.list(options) +``` + +Delete account tag: +```ruby +tags.remove('name-of-tag-to-remove') +``` + +Get account tag limit information: +```ruby +tags.limits +``` + +--- + +More Documentation +------------------ +See the official [Mailgun Tags New Docs](https://documentation.mailgun.com/docs/mailgun/api-reference/send/mailgun/tags-new) +for more information diff --git a/lib/mailgun/client.rb b/lib/mailgun/client.rb index bea43ca..74fd5f3 100644 --- a/lib/mailgun/client.rb +++ b/lib/mailgun/client.rb @@ -162,16 +162,8 @@ def get(resource_path, params = {}, accept = '*/*') # @param [Hash] data This should be a standard Hash # containing required parameters for the requested resource. # @return [Mailgun::Response] A Mailgun::Response object. - def put(resource_path, params, body_params = false) - response = - if body_params - @http_client.put(resource_path) do |request| - request['Content-Type'] = 'application/json' - request.params = params.to_json - end - else - @http_client.put(resource_path, params) - end + def put(resource_path, data, headers = {}) + response = @http_client.put(resource_path, data, headers) Response.new(response) rescue => err raise communication_error err diff --git a/lib/mailgun/tags/analytics_tags.rb b/lib/mailgun/tags/analytics_tags.rb index 3ed1b30..323afd2 100644 --- a/lib/mailgun/tags/analytics_tags.rb +++ b/lib/mailgun/tags/analytics_tags.rb @@ -11,18 +11,47 @@ def initialize(client = Mailgun::Client.new(Mailgun.api_key, Mailgun.api_host || @client = client end + # Public: Update account tag + # + # tag - [String] The tag to update. + # description - [String] The updated tag description. + # + # Returns [Boolean] true or false def update(tag, description) - @client.put('analytics/tags', { tag: tag, description: description }, body_params: true ).to_h['message'] == 'Tag updated' + @client.put('analytics/tags', { tag: tag, description: description }.to_json, { "Content-Type" => "application/json" } ).to_h['message'] == 'Tag updated' end + # Public: Post query to list account tags or search for single tag + # + # options - [Hash] of + # include_subaccounts - [Boolean] Boolean indicating whether or not to include data from all subaccounts. Default false. + # include_metrics - [Boolean] Boolean indicating whether or not to include metrics for tags. Default false. When true max limit is 20. + # tag - [string] The tag or tag prefix. + # pagination - [Object] + # sort - [String] Colon-separated value indicating column name and sort direction e.g. 'timestamp:desc'. + # skip - [Integer] The number of items to skip over when satisfying the request. + # limit - [Integer] The maximum number of items returned (100 max). + # total - [Integer] The total number of tags matching the search criteria. + # include_total - [Boolean] Boolean indicating whether or not to include total number of items. Default false. + + # + # Returns [Hash] Information on the requested tags. def list(options = {}) @client.post('analytics/tags', options).to_h['items'] end + # Public: Delete account tag + # + # tag - [String] The tag to delete. + # + # Returns [Boolean] true or false def remove(tag) @client.delete('analytics/tags', { tag: tag }, body_params: true).to_h['message'] == 'Tag deleted' end + # Public: Get account tag limit information + # + # Returns [Hash] Information on the tag limits. def limits @client.get('analytics/tags/limits').to_h end diff --git a/spec/integration/analytics_tags_spec.rb b/spec/integration/analytics_tags_spec.rb new file mode 100644 index 0000000..f8d2e62 --- /dev/null +++ b/spec/integration/analytics_tags_spec.rb @@ -0,0 +1,51 @@ +require 'spec_helper' +require 'mailgun' + +vcr_opts = { cassette_name: 'analytics_tags' } + +describe 'AnalyticsTags', vcr: vcr_opts do + let(:api_version) { APIVERSION } + let(:mg_client) { Mailgun::Client.new(APIKEY, APIHOST, api_version, SSL) } + let(:mg_obj) { Mailgun::AnalyticsTags.new(mg_client) } + let(:api_version) { 'v1' } + + describe '#update' do + it 'updates a tag' do + response = mg_obj.update('test1', 'test_description') + + expect(response).to be_truthy + end + end + + describe '#list' do + it 'returns a list of tags' do + response = mg_obj.list( + { + pagination: { + sort: 'lastseen:desc', + limit: 10 + }, + include_subaccounts: true + }) + + expect(response[0]['account_id']).to eq('test') + expect(response[0]['tag']).to eq('test1') + end + end + + describe '#remove' do + it 'removes a tag' do + response = mg_obj.remove('test1') + + expect(response).to be_truthy + end + end + + context '#limits' do + it 'returns limits' do + response = mg_obj.limits + + expect(response['limit']).to eq(100000) + end + end +end diff --git a/vcr_cassettes/analytics_tags.yml b/vcr_cassettes/analytics_tags.yml new file mode 100644 index 0000000..93c44d1 --- /dev/null +++ b/vcr_cassettes/analytics_tags.yml @@ -0,0 +1,187 @@ +--- +http_interactions: +- request: + method: post + uri: https://api.mailgun.net/v1/analytics/tags + body: + encoding: UTF-8 + string: include_subaccounts=true&pagination=%7Bsort%3A+%22lastseen%3Adesc%22%2C+limit%3A+10%7D + headers: + User-Agent: + - mailgun-sdk-ruby/1.4.1 + Accept: + - "*/*" + Authorization: + - Basic xxx + Content-Type: + - application/x-www-form-urlencoded + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + response: + status: + code: 200 + message: OK + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - no-store + Content-Length: + - '317' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 28 Jan 2026 18:49:42 GMT + Strict-Transport-Security: + - max-age=63072000; includeSubDomains + X-Mailgun-Key-Id: + - xxx + X-Xss-Protection: + - 1; mode=block + body: + encoding: UTF-8 + string: '{"items":[{"account_id":"test","parent_account_id":"test","tag":"test1","description":"","first_seen":"Wed, + 28 Jan 2026 18:27:11 +0000","last_seen":"Wed, 28 Jan 2026 18:00:00 +0000","metrics":{},"account_name":"Alex + Lebedev"}],"pagination":{"sort":"lastseen:desc","limit":10}} + + ' + recorded_at: Wed, 28 Jan 2026 18:49:42 GMT +- request: + method: get + uri: https://api.mailgun.net/v1/analytics/tags/limits + body: + encoding: US-ASCII + string: '' + headers: + User-Agent: + - mailgun-sdk-ruby/1.4.1 + Accept: + - "*/*" + Authorization: + - Basic xxx + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + response: + status: + code: 200 + message: OK + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - no-store + Content-Length: + - '49' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 28 Jan 2026 18:55:47 GMT + Strict-Transport-Security: + - max-age=63072000; includeSubDomains + X-Mailgun-Key-Id: + - xxx + X-Xss-Protection: + - 1; mode=block + body: + encoding: UTF-8 + string: '{"limit":100000,"count":1,"limit_reached":false} + + ' + recorded_at: Wed, 28 Jan 2026 18:55:47 GMT +- request: + method: put + uri: https://api.mailgun.net/v1/analytics/tags + body: + encoding: UTF-8 + string: '{"tag":"test1","description":"test_description"}' + headers: + User-Agent: + - mailgun-sdk-ruby/1.4.2 + Accept: + - "*/*" + Content-Type: + - application/json + Authorization: + - Basic xxx + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + response: + status: + code: 200 + message: OK + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - no-store + Content-Length: + - '26' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 28 Jan 2026 20:04:23 GMT + Strict-Transport-Security: + - max-age=63072000; includeSubDomains + X-Mailgun-Key-Id: + - xxx + X-Xss-Protection: + - 1; mode=block + body: + encoding: UTF-8 + string: '{"message":"Tag updated"} + + ' + recorded_at: Wed, 28 Jan 2026 20:04:23 GMT +- request: + method: delete + uri: https://api.mailgun.net/v1/analytics/tags + body: + encoding: UTF-8 + string: '{"tag":"test1"}' + headers: + User-Agent: + - mailgun-sdk-ruby/1.4.2 + Accept: + - "*/*" + Authorization: + - Basic xxx + Content-Type: + - application/x-www-form-urlencoded + Accept-Encoding: + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 + response: + status: + code: 200 + message: OK + headers: + Access-Control-Allow-Credentials: + - 'true' + Access-Control-Allow-Origin: + - "*" + Cache-Control: + - no-store + Content-Length: + - '26' + Content-Type: + - application/json; charset=utf-8 + Date: + - Wed, 28 Jan 2026 20:05:54 GMT + Strict-Transport-Security: + - max-age=63072000; includeSubDomains + X-Mailgun-Key-Id: + - xxx + X-Xss-Protection: + - 1; mode=block + body: + encoding: UTF-8 + string: '{"message":"Tag deleted"} + + ' + recorded_at: Wed, 28 Jan 2026 20:05:54 GMT +recorded_with: VCR 6.4.0